我正在尝试为我的数据集生成更多变量。我的数据存储在多个文件中,由于内存限制,使用熊猫我一次只能读取一个文件。每个csv文件都有一个月的数据,如下所示:
Index Date Sender Recipient Quantity Type
------------------------------------------------------------------------
79XT 26-03-19 Adam Tiffany 72 Box
57ZY 14-03-19 Josh Ross 13 Snack
29UQ 19-03-19 Adam Alex 60 Fruit
56PY 06-03-19 Lucy Alex 29 Book
41BR 28-03-19 Josh Steve 33 Snack
现在我正在尝试根据每个发件人的历史为每行生成更多特征,并将这些特征加入到数据框中。例如:
Index Date Sender Recipient Quantity Type Days Since Days Since Cumulative Quantity Increase First Shipment
Previous Shipment First Shipment Quantity from Previous Shipment to This Recipient?
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
79XT 26-03-19 Adam Tiffany 72 Box 7 62 1792 12 0
57ZY 14-03-19 Josh Ross 13 Snack NaN NaN 13 NaN 1
29UQ 19-03-19 Adam Alex 60 Fruit 5 55 1730 -7 1
56PY 06-03-19 Lucy Alex 29 Book 23 32 88 -4 0
41BR 28-03-19 Josh Steve 33 Snack 14 14 46 20 1
正如您从上面所需的dataframe中看到的那样,新变量是根据发送者先前的观察生成的。生成此类功能的计算成本最低的方法是什么?我需要从我所有的每月csv文件中获取信息来收集此类数据。有超过200,000个唯一的发送者,因此需要数周的时间来读取csv文件并为每个唯一的发送者生成dataframe和csv文件,并将此数据与每月csv文件合并。我知道dask和dask分布式,但我想知道是否有更简单的方法来实现我正在尝试做的事情。
在这里我有一个不同的方法。我会试着
csv
转换为parque
(最终看到这个答案)更改dtype
。至少df['Date'] = df['Date'].astype("M8")
或
df['Date'] = pd.to_datetime(df['Date'])
import dask.dataframe as dd
df = dd.read_parquet('processed')
df.to_parquet('processed2', partition_on='Sender')
现在您在每个Sender=username
中都有许多文件,您应该将所有文件合并到一个文件中
您现在可以为每个Sender=username
创建函数
def fun(df):
df = df.sort_values("Date")
df["Day Since Prev Shipment"] = df["Date"].diff().dt.days
df["Day Since First Shipment"](df["Date"] - df["Date"].min()).dt.days
df["Cumulative Quantity"] = df["Quantity"].cumsum()
df["Quantity difference"] = df["Quantity"].diff()
grp = df.groupby("Recipient")["Date"].min().reset_index(name="First Shipment")
df = pd.merge(df, grp, how="left", on="Recipient")
df["First Shipment"] = (df["Date"]==df["First Shipment"]).astype("int8")
return df
我在你的问题中看到了多个子问题。
df = df.merge(df.groupby("sender").agg(first_occurence_date=("Date","min"))["sender", "first_occurrence_date"], on="sender", how="left")
# Computationally likely inefficient, and doesn't solve multiple file-issue immediately.
. feather
作为一种高效的存储格式。这种标准会发生变化,因此始终保留.csv
作为备份。您可以像这样将文件编写为featherdf。to_feather("filename")
考虑使用pd. factorize()
对字符串进行因式分解,如Pandas Docs:pd.Factorize()中所述-我还没有看到这方面的基准,但是比较int
比string
更快。
最后,考虑建立一个小型sqlite3数据库来读取单个文件并存储它们。否则,获得第一次出现将是一种痛苦,因为您必须不断覆盖旧值并多次执行计算成本高昂的操作。