Python PANDAS:从pandas / numpy转换为dask dataframe / array

时间:2018-02-14 19:16:15

标签: python pandas numpy dask

我正在尝试使用优秀的dask库将程序转换为可并行化/多线程。这是我正在进行转换的程序:

Python PANDAS: Stack by Enumerated Date to Create Records Vectorized

import pandas as pd
import numpy as np
import dask.dataframe as dd
import dask.array as da
from io import StringIO

test_data = '''id,transaction_dt,units,measures
               1,2018-01-01,4,30.5
               1,2018-01-03,4,26.3
               2,2018-01-01,3,12.7
               2,2018-01-03,3,8.8'''

df_test = pd.read_csv(StringIO(test_data), sep=',')
df_test['transaction_dt'] = pd.to_datetime(df_test['transaction_dt'])

df_test = df_test.loc[np.repeat(df_test.index, df_test['units'])]
df_test['transaction_dt'] += pd.to_timedelta(df_test.groupby(level=0).cumcount(), unit='d')
df_test = df_test.reset_index(drop=True)

预期结果:

id,transaction_dt,measures
1,2018-01-01,30.5
1,2018-01-02,30.5
1,2018-01-03,30.5
1,2018-01-04,30.5
1,2018-01-03,26.3
1,2018-01-04,26.3
1,2018-01-05,26.3
1,2018-01-06,26.3
2,2018-01-01,12.7
2,2018-01-02,12.7
2,2018-01-03,12.7
2,2018-01-03,8.8
2,2018-01-04,8.8
2,2018-01-05,8.8 

我想到这可能是尝试并行化的一个很好的候选者,因为单独的dask分区不需要知道彼此之间的任何事情来完成所需的操作。以下是我认为它可能起作用的天真表示:

dd_test = dd.from_pandas(df_test, npartitions=3)

dd_test = dd_test.loc[da.repeat(dd_test.index, dd_test['units'])]
dd_test['transaction_dt'] += dd_test.to_timedelta(dd.groupby(level=0).cumcount(), unit='d')
dd_test = dd_test.reset_index(drop=True)

到目前为止,我一直在努力解决以下错误或惯用的差异:

  1. “NotImplementedError:仅支持整数值重复。” 我试图将索引转换为int列/数组以尝试,但仍然遇到问题。
  2. 2. dask不支持变异运算符:“+ =”

    3.没有dask .to_timedelta()参数

    4.没有dask .cumcount()(但我认为.cumsum()是可互换的?!)

    如果有任何dask专家可以让我知道是否存在妨碍我尝试这个或任何实施技巧的根本障碍,那将是一个很大的帮助!

    修改

    我认为自从发布问题后我已经取得了一些进展:

    dd_test = dd.from_pandas(df_test, npartitions=3)
    dd_test['helper'] = 1
    
    dd_test = dd_test.loc[da.repeat(dd_test.index, dd_test['units'])]
    dd_test['transaction_dt'] = dd_test['transaction_dt'] + (dd.test.groupby('id')['helper'].cumsum()).astype('timedelta64[D]') 
    dd_test = dd_test.reset_index(drop=True)
    

    但是,我仍然坚持dask数组重复错误。任何提示仍然欢迎。

1 个答案:

答案 0 :(得分:1)

不确定这是否正是您正在寻找的,但我使用np.repeat替换了da.repeat,并将明确转换为dd_test.indexdd_test['units']到numpy数组,最后添加dd_test['transaction_dt'].astype('M8[us]')到你的timedelta计算。

df_test = pd.read_csv(StringIO(test_data), sep=',')

dd_test = dd.from_pandas(df_test, npartitions=3)
dd_test['helper'] = 1

dd_test = dd_test.loc[np.repeat(np.array(dd_test.index), 
np.array(dd_test['units']))]
dd_test['transaction_dt'] = dd_test['transaction_dt'].astype('M8[us]') + (dd_test.groupby('id')['helper'].cumsum()).astype('timedelta64[D]')
dd_test = dd_test.reset_index(drop=True)

df_expected = dd_test.compute()