Amirali Sharifzad
09/20/2024, 11:50 PMPandasDataFrameResult. The error I get is ValueError: array length 10000 does not match index length 9871. the code looks simple:
output_columns = [
"ids",
"sum_contributions",
]
df = dr.execute(output_columns)
This makes sense because in sum_contributions I am filtering out some records. Is there a way to rewrite this to tell the Driver to do a left join - or another way to avoid this error? Is the only solution creating a function that handles all the joining logic and simply outputs the final df?Stefan Krawczyk
09/20/2024, 11:52 PMStefan Krawczyk
09/20/2024, 11:53 PMAmirali Sharifzad
09/20/2024, 11:54 PMIf you have a use case for a custom ResultBuilder, tell us on Slack or via a GitHub issues.Stefan Krawczyk
09/20/2024, 11:55 PMfrom hamilton import driver, base
import functions
import typing
from hamilton import lifecycle
class MyCustomBuilder(lifecycle.ResultBuilder):
# add a constructor if you need to
@staticmethod
def build_result(**outputs: typing.Dict[str, typing.Any]) -> pd.DataFrame:
"""Custom function you fill in"""
# your logic would go here
return pd.DataFrame(outputs).head(1)
# Create the driver -- passing in an empty config and the functions module
dr = (
driver.Builder()
.with_config({})
.with_modules(functions)
.with_adapters(MyCustomBuilder())
.build()
)
result = dr.execute(
[
"spend",
"signups",
"avg_3wk_spend"],
inputs=load_data().to_dict(orient="series")
)Amirali Sharifzad
09/20/2024, 11:56 PMStefan Krawczyk
09/20/2024, 11:57 PMStefan Krawczyk
09/20/2024, 11:57 PMStefan Krawczyk
09/20/2024, 11:58 PMAmirali Sharifzad
09/20/2024, 11:59 PMStefan Krawczyk
09/21/2024, 12:00 AMStefan Krawczyk
09/21/2024, 12:01 AMAmirali Sharifzad
09/21/2024, 12:05 AMAmirali Sharifzad
09/21/2024, 12:07 AMStefan Krawczyk
09/21/2024, 12:12 AMAmirali Sharifzad
09/21/2024, 12:13 AMStefan Krawczyk
09/21/2024, 12:16 AMStefan Krawczyk
09/21/2024, 12:17 AMStefan Krawczyk
09/21/2024, 12:21 AMAmirali Sharifzad
09/21/2024, 12:29 AMIf you're doing a bake off - consider trying polars on a single machine as a base line.
3. Yeah the thing to think about is the datatransfer between processes has to be worth it. What are the things to consider here? I know that we need some layer of distributed processing for the scale of data we use, but I don't fully understand this point. Is it ensuring the tasks are "beefy"?
a. I know that Hamilton materializes the data in every node (hamilton function). This means the full data needs to fit in memory. Is this going to be a big blocker for us as we scale?Stefan Krawczyk
09/21/2024, 12:42 AMdef df_batch(large_df: pd.DataFrame) -> Parallelizable[pd.DataFrame]:
for i in range(0, len(df), BATCH_SIZE):
yield df.iloc[i:i + BATCH_SIZE]
def my_func(df_batch: pd.DataFrame) -> ...
that should work
> consider trying polars on a single machine as a base line.
Polars is more memory efficient than Pandas. They have a way to “batch” over data with LazyFrame. It could give you a baseline to test a “distributed” solution against.
> Is it ensuring the tasks are “beefy”?
Yep. You need the task computation to be long enough so that the time that it takes to serialize and deserialize the data is worth parallelizing it.
E.g. time to serialize and deserialize * N, should be less than the time to run the task in serial, where N is how many things in parallel you’re doing.
> I know that Hamilton materializes the data in every node (hamilton function). This means the full data needs to fit in memory. Is this going to be a big blocker for us as we scale?
No. You’d just change the data type / chunk the data appropriately. Hamilton is data type agnostic, it doesn’t care whether you’re using pandas, polars, pyspark, etc. So you’d use the data type / computation appropriate for your scale. Does that make sense? Feel free to come to office hours on Tuesday next week (9:30 AM PT) and someone can explain more there.Stefan Krawczyk
09/21/2024, 12:43 AMAmirali Sharifzad
09/21/2024, 12:48 AMStefan Krawczyk
09/21/2024, 12:50 AMAmirali Sharifzad
09/21/2024, 12:51 AM