Seth Stokes
09/18/2024, 3:40 PMSOURCE1_HIST_FILE determines the first_run flag in the config, and in the end,
load_source1_data.py will be a part of a subdag.
How can I make sure that every save_to node saves out the file, each time it goes through that node?
# load_source1_data.py
@config.when(first_run=True)
@save_to.parquet(path=value(SOURCE1_HIST_FILE), output_name_="saved_current_data_source1")
def current_data_source1__first_run(
processed_data_source1: Collect[pd.DataFrame]
) -> pd.DataFrame:
return pd.concat(processed_data_source1, axis="index", ignore_index=True)
@config.when_not(first_run=True)
@load_from.parquet(path=value(SOURCE1_HIST_FILE), inject_="last_run_source_source1")
@save_to.parquet(path=value(SOURCE1_HIST_FILE), output_name_="saved_current_data_source1")
def current_data_source1__subsq_run(
processed_data_source1: Collect[pd.DataFrame], last_run_data_source1: pd.DataFrame
) -> pd.DataFrame:
processed_df = pd.concat(processed_data_source1, axis="index", ignore_index=True)
return pd.concat([last_run_source_source1, processed_df], axis="index", ignore_index=True)Stefan Krawczyk
09/18/2024, 4:23 PMdict IIRC.Seth Stokes
09/18/2024, 5:31 PM[v for v in dr.list_available_variables() if v.tags.get("hamilton.data_saver")]Seth Stokes
09/18/2024, 7:46 PMsavers = [node for node in dr.what_is_upstream_of("current_data_source1") if node.tags.get("hamilton.data_saver")]
dr.execute(savers)
However, saved_current_data_source1 cannot be seen. since i guess technically its not upstream.Stefan Krawczyk
09/18/2024, 7:47 PM[v for v in dr.list_available_variables() if v.tags.get("hamilton.data_saver") and "current_data_source1" in v.name]
the node is there, it’ll just be prefixed.Seth Stokes
09/18/2024, 8:00 PM@subdag(
load_source1_data, load_source2_data
)
def norm_data(
current_data_source1: pd.DataFrame,
current_data_source2: pd.DataFrame
) -> pd.DataFrame:
current_data_source1, current_data_source2
# some more work
return ...
final_node = "norm_data"
final_df = dr.execute([final_node])
savers = [v for v in dr.what_is_upstream_of(final_node) if v.tags.get("hamilton.data_saver") or final_node in v.name]
dr.execute(savers)
So if i had multiple subdags, this could be a way to save every hamliton.data_saver node it went though?Stefan Krawczyk
09/18/2024, 8:01 PMSeth Stokes
09/18/2024, 8:01 PMStefan Krawczyk
09/18/2024, 8:13 PM@subdag(
load_source1_data, load_source2_data
)
def norm_data(
current_data_source1: pd.DataFrame,
current_data_source2: pd.DataFrame,
saved_current_data_source1: dict # declare but don't use it...
) -> pd.DataFrame:
current_data_source1, current_data_source2
# some more work
return ...
As you have with finding the tags on nodes and then requesting them.
outputs = [v for v in dr.list_available_variables() if v.tags.get("hamilton.data_saver")]
dr.execute(outputs, inputs=...)Seth Stokes
09/18/2024, 8:54 PMfinal_node = "norm_data"
final_df = dr.execute([final_node])
savers = [f"saved_{final_node}"] + [v for v in dr.what_is_upstream_of(final_node) if v.tags.get("hamilton.data_saver")]
dr.execute(savers)
Should I expect this not to work?
I think its getting hung up in the driver.Stefan Krawczyk
09/18/2024, 9:03 PMI think its getting hung up in the driver.which line? Did you mean to do:
final_df = dr.execute([final_node])that is executing things?
Seth Stokes
09/18/2024, 9:09 PMdr.execute(savers)Stefan Krawczyk
09/18/2024, 9:14 PMsavers ? does it contain what you want?Seth Stokes
09/18/2024, 9:24 PMSeth Stokes
09/18/2024, 9:34 PMsavers_all = {v.name for v in dr.list_available_variables() if v.tags.get("hamilton.data_saver")}
savers = [v.name for v in dr.what_is_upstream_of(f"saved_{final_node}") if v.tags.get("hamilton.data_saver") and v.name in savers_all]
this was an idea, but it appears that dr.what_is_upstream_of upstream node results that have save_to attached to it does not reveal itself to the dagStefan Krawczyk
09/18/2024, 9:43 PMStefan Krawczyk
09/18/2024, 9:43 PMwhat_is_upstream_of doesn’t return everythingStefan Krawczyk
09/18/2024, 9:43 PMStefan Krawczyk
09/18/2024, 9:43 PMStefan Krawczyk
09/18/2024, 9:45 PM{v.name for v in dr.list_available_variables() if v.tags.get(“hamilton.data_saver”)}this should include the
save_to nodesStefan Krawczyk
09/18/2024, 9:46 PMv.name for v in dr.what_is_upstream_of(f”saved_{final_node}“)this wont — because the save_to nodes aren’t upstream of it.
Stefan Krawczyk
09/18/2024, 9:47 PMnorm_data.NAME_OF_SAVE_TO should be what the node names look likeSeth Stokes
09/18/2024, 9:47 PMsave_nodes upstream of and attached to the node I am asking for?Stefan Krawczyk
09/18/2024, 9:49 PMupstream? why not downstream?Stefan Krawczyk
09/18/2024, 9:49 PMStefan Krawczyk
09/18/2024, 9:51 PM@tag_outputs(foobar={"tag_key": "tag_value"})
@save_to.csv(path=source("fpath"), output_name_="foobar")
def a(input: pd.Series) -> pd.DataFrame:
return input % 7
then search for that tag key & value.Seth Stokes
09/18/2024, 9:52 PMupstream because I am going to be asking for the "sink"/outermost nodeSeth Stokes
09/18/2024, 9:53 PMsave_to?Stefan Krawczyk
09/18/2024, 10:10 PM[v for v in dr.list_available_variables(tag_filter={"tag_key": "tag_value", "hamilton.data_saver": None})]Seth Stokes
09/18/2024, 10:12 PMSeth Stokes
09/18/2024, 10:16 PMpipe?
Or is pipe not compatible with Parallelizable?
@config.when_not(first_run=True)
@tag(table="raw")
@pipe(
step(
_filter_from_highwatermark, date_col="COB_Date", highwatermark_date=source("highwatermark_date")
)
)
@save_to.parquet(path=value(HIST_FILE_RAW), output_name_="saved_current_data_raw")
def raw_volumes_pre__subsq_run(
file_path: str, read_fn: callable) -> pd.DataFrame:
return read_fn(file_path).assign(COB_Date=lambda _df: pd.to_datetime(_df["COB_Date"]), SOURCE_FILE=file_path)
ValueError: Error: raw_volumes_pre.with_filter_from_highwatermark is expecting file_path:<class 'pandas.core.frame.DataFrame'>, but found file_path:hamilton.htypes.Parallelizable[str].
Hamilton does not consider these types to be equivalent. If you believe they are equivalent, please reach out to the developers. Note that, if you have types that are equivalent for your purposes, you can create a graph adapter that checks the types against each other in a more lenient manner.Stefan Krawczyk
09/18/2024, 10:38 PMfile_path is a string — but with _filter_from_highwatermark it’s annotated as a dataframe?Seth Stokes
09/19/2024, 2:11 AMfile_path comes from upstream Parallelizable[str] node. The body of the function reads the data, and I want pipe to filter the results via _filter_from_highwatermark . I believe that’s everything that’s trying to occur here. Let me know if any of those expectations are wrong and if/how that can/could happen.Stefan Krawczyk
09/19/2024, 3:31 AMValueError: Error: raw_volumes_pre.with_filter_from_highwatermark is expecting file_path:<class ‘*pandas.core.frame.DataFrame*’>, but found file_path:hamilton.htypes.Parallelizable[str].but your code above doesn’t show that
Seth Stokes
09/19/2024, 2:58 PM@config.when_not(first_run=True)
def file_path__first_run(files_to_load: Optional[list] = None) -> Parallelizable[str]:
for f in files_to_load:
yield f
is this what youre missing?Stefan Krawczyk
09/19/2024, 3:53 PM_filter_from_highwatermark function?Seth Stokes
09/19/2024, 3:53 PMdef _filter_from_highwatermark(
df: pd.DataFrame, date_col: str, highwatermark_date: datetime
) -> pd.DataFrame:
"""Filter the new data where `date_col` > `highwatermark_date` since each new file's data is MTD, if this is ran each day only the new data rows are needed."""
return df.set_index(date_col).loc[lambda dt: dt > highwatermark_date].reset_index()Stefan Krawczyk
09/19/2024, 5:28 PM_filter_from_highwatermark expects a dataframe, not a string.
e.g. you have
file_path__first_run -> outputting a string -> going into _filter_from_highwatermark that expects a dataframe.Seth Stokes
09/19/2024, 5:30 PMraw_volumes_pre?Stefan Krawczyk
09/19/2024, 5:31 PMpipe runs before, i.e. it uses the first argument as the dependency to modify and return.Stefan Krawczyk
09/19/2024, 5:31 PMpost_pipe will do what you want (it’s currently under active development)Seth Stokes
09/19/2024, 5:32 PM