web-dev-qa-db-ja.com

dask dataframe apply meta

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#メタデータ )。

metaとは何ですか?そして、私はそれをどのように定義するべきですか?

python 3.6dask 0.14.3およびpandas 0.20.2の使用

14
Matti Lyra

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')))
18
mdurant