将lambda函数应用于dask数据框

时间:2019-03-02 06:29:04

标签: python dataframe dask

我希望将lambda函数应用于dask数据框,以更改列中的标签(如果其小于一定百分比)。我使用的方法对于pandas数据框效果很好,但是相同的代码对dask数据框无效。代码如下。

df = pd.DataFrame({'A':['ant','ant','cherry', 'bee', 'ant'], 'B':['cat','peach', 'cat', 'cat', 'peach'], 'C':['dog','dog','roo', 'emu', 'emu']})
ddf = dd.from_pandas(df, npartitions=2)

df:

输出:

     A     B      C
0   ant    cat   dog
1   ant    peach dog
2   cherry cat   roo
3   bee    cat   emu
4   ant    peach emu
ddf.compute()

输出:

     A     B      C
0   ant    cat   dog
1   ant    peach dog
2   cherry cat   roo
3   bee    cat   emu
4   ant    peach emu
list_ = ['B','C']
df.apply(lambda x: x.mask(x.map(x.value_counts(normalize=True))<.5, 'other') if x.name not in list_ else x)

输出:

     A     B      C
0   ant    cat   dog
1   ant    peach dog
2   other  cat   roo
3   other  cat   emu
4   ant    peach emu

对dask数据框执行相同操作:

ddf.apply(lambda x: x.mask(x.map(x.value_counts(normalize=True))<.5, 'other') if x.name not in list_ else x,axis=1).compute()

输出(给出警告,而不是必需的输出):

/home/michael/env/lib/python3.5/site-packages/dask/dataframe/core.py:3107: UserWarning: `meta` is not specified, inferred from partial data. Please provide `meta` if the result is unexpected.
  Before: .apply(func)
  After:  .apply(func, meta={'x': 'f8', 'y': 'f8'}) for dataframe result
  or:     .apply(func, meta=('x', 'f8'))            for series result
  warnings.warn(msg)
      A       B       C
0   other   other   other
1   other   other   other
2   other   other   other
3   other   other   other
4   other   other   other

有人可以帮助我获得dask数据框实例的所需输出。

谢谢

迈克尔

1 个答案:

答案 0 :(得分:1)

在熊猫和傻子案例中,您执行的操作不同:对于后者,您有axis=1,因此最终替换了在给定行,这就是全部。

如果更改为axis=0,则会看到一个异常。这是因为要计算第一个分区,您还需要将整个数据帧也传递给lambda函数-否则如何获得value_counts?

您的问题的解决方案是分别获取值计数。您可以显式计算此结果(结果很小)或将其传递给lambda。还要注意,走这条路意味着您可以避免使用apply来代替map,并使事情变得更明确。在这里,我只选择一列,您可以循环。

vc = ddf.A.value_counts().compute()
vc /= vc.sum()  # because dask's value_count doesn't normalise

def simple_map(df):
    df['A'] = df['A'].map(lambda x: x if vc[x] > 0.5 else 'other')
    return df

ddf.map_partitions(simple_map, meta=df[:0]).compute()