【问题标题】:dask dataframe apply metadask 数据框应用元
【发布时间】:2017-11-10 00:00:35
【问题描述】:

我想对 dask 数据帧的单列进行频率计数。该代码有效,但我收到 warning 抱怨 meta 未定义。如果我尝试定义meta,则会收到错误AttributeError: 'DataFrame' object has no attribute 'name'。对于这个特定的用例,我似乎不需要定义meta,但我想知道如何做以供将来参考。

虚拟数据框和列频率

import pandas as pd
from dask import dataframe as dd

df = pd.DataFrame([['Sam', 'Alex', 'David', 'Sarah', 'Alice', 'Sam', 'Anna'],
                   ['Sam', 'David', 'David', 'Alice', 'Sam', 'Alice', 'Sam'],
                   [12, 10, 15, 23, 18, 20, 26]],
                  index=['Column A', 'Column B', 'Column C']).T
dask_df = dd.from_pandas(df)

In [39]: dask_df.head()
Out[39]: 
  Column A Column B Column C
0      Sam      Sam       12
1     Alex    David       10
2    David    David       15
3    Sarah    Alice       23
4    Alice      Sam       18

(dask_df.groupby('Column B')
        .apply(lambda group: len(group))
       ).compute()

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)
Out[60]: 
Column B
Alice    2
David    2
Sam      3
dtype: int64

尝试定义meta 会产生AttributeError

 (dask_df.groupby('Column B')
         .apply(lambda d: len(d), meta={'Column B': 'int'})).compute()

这个也一样

 (dask_df.groupby('Column B')
         .apply(lambda d: len(d), meta=pd.DataFrame({'Column B': 'int'}))).compute()

如果我尝试将dtype 设置为int 而不是"int" 或者就此而言'f8'np.float64 则相同,所以看起来不是dtype 导致了问题。

meta 上的文档似乎暗示我应该做我想做的事 (http://dask.pydata.org/en/latest/dataframe-design.html#metadata)。

meta 是什么?我应该如何定义它?

使用python 3.6 dask 0.14.3pandas 0.20.2

【问题讨论】:

  • 嗯,不知道为什么会失败。这工作meta=('Column B', 'int') 吗?
  • 不回答你的问题,但是dask_df.groupby('Column B').count().compute() 怎么样?这将获取每列中有效值的数量,而不是长度。 dask_df['Column B'].value_counts().compute() 是更准确的翻译。我认为的错误是因为输出将 B 列作为 index 而不是列名。
  • 这两个似乎都做对了,不知道哪一个最有效

标签: python pandas dask


【解决方案1】:

meta 是计算输出的名称/类型的规定。这是必需的,因为apply() 足够灵活,它可以从数据帧中生成几乎任何东西。如您所见,如果您不提供meta,那么 dask 实际上会计算部分数据,以查看类型应该是什么——这很好,但您应该知道它正在发生。 通过提供输出的零行版本(数据帧或系列)或仅提供类型,您可以避免这种预计算(这可能很昂贵)并且在您知道输出应该是什么样子时更加明确。

你的计算输出实际上是一个序列,所以下面是最简单的工作

(dask_df.groupby('Column B')
     .apply(len, meta=('int'))).compute()

但更准确的应该是

(dask_df.groupby('Column B')
     .apply(len, meta=pd.Series(dtype='int', name='Column B')))

【讨论】:

  • 包含完整的 pd.Series 元数据是否有任何性能提升?
  • 不,但它更明确,并且在某些情况下允许您更好地控制,例如,对索引的名称和类型。
猜你喜欢
  • 2022-08-06
  • 1970-01-01
  • 1970-01-01
  • 2021-02-12
  • 1970-01-01
  • 2019-08-25
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
相关资源
最近更新 更多