在小型/分区数据帧上使用延迟延迟

时间:2019-09-24 16:52:17

标签: pandas parallel-processing time-series dask dask-delayed

我正在处理时间序列数据,该数据的格式为每一行都是ID /时间/数据的单个实例。这意味着对于每个ID,行并不对应于1到1。每个ID跨时间都有很多行。

我正在尝试使用dask delay来使函数在整个ID序列上运行(这是有意义的,因为该操作不会相互影响,所以该操作应该能够同时在每个单独的ID上运行)。为此,我首先循环遍历每个ID标记,从该ID中提取/定位所有数据(在熊猫中使用.loc,因此它是单独的“ mini” df),然后延迟对mini df的函数调用,添加包含延迟值的列,并将其添加到所有mini dfs的列表中。在for循环结束时,我想一次在所有mini-df上调用dask.compute(),但是由于某种原因,mini df的值仍然被延迟。下面,我将发布一些伪代码,说明我刚才试图解释的内容。

我觉得这可能不是解决此问题的最佳方法,但这在当时是很有意义的,我无法理解到底出了什么问题,因此将不胜感激。

这就是我想要做的:

list_of_mini_dfs = []
for id in big_df:

    curr_df = big_df.loc[big_df['id'] == id]
    curr_df['new value 1'] = dask.delayed(myfunc)(args1)
    curr_df['new value 2'] = dask.delayed(myfunc)(args2) #same func as previous line

    list_of_mini_dfs.append(curr_df)

list_of_mini_dfs = dask.delayed(list_of_mini_dfs).compute()

Concat all mini dfs into new big df.

从代码中可以看到,由于每个ID散布在行中,因此我必须进入我的大/总体数据框以提取每个ID的数据序列。我希望能够对单个ID的数据调用延迟的函数,然后将函数调用中的值返回到大/整体数据框中。

当前该方法不起作用,当我将所有微型数据帧重新组合在一起时,我延迟的两个值仍然被延迟,这使我认为这是由于我在df和尝试计算数据帧列表。我只是看不到如何解决。

希望这是相对清楚的,感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

IIUC,您正在尝试使用dask进行某种transform的操作。

import pandas as pd
import dask.dataframe as dd
import numpy as np

# generate big_df
dates = pd.date_range(start='2019-01-01',
                      end='2020-01-01')
l = len(dates)
out = []
for i in range(1000):
    df = pd.DataFrame({"ID":[i]*l,
                       "date": dates,
                       "data0": np.random.randn(l),
                       "data1": np.random.randn(l)})

    out.append(df)

big_df = pd.concat(out, ignore_index=True)\
           .sample(frac=1)\
           .reset_index(drop=True)

现在您要在列fundata0上应用函数data1

熊猫

out = big_df.groupby("ID")[["data0","data1"]]\
            .apply(fun)\
            .reset_index()

df_pd = pd.merge(big_df, out, how="left", on="ID" )

黄昏

df = dd.from_pandas(big_df, npartitions=4)

out = df.groupby("ID")[["data0","data1"]]\
        .apply(fun, meta={'data0':'f8',
                          'data1':'f8'})\
        .rename(columns={'data0': 'new_values0',
                         'data1': 'new_values1'})\
        .compute() # Here you need to compute otherwise you'll get NaNs

df_dask = dd.merge(df, out,
                   how="left", 
                   left_on=["ID"],
                   right_index=True)

dask版本不一定比pandas版本快。特别是如果您的df可以放入RAM。