Dask + Pandas:返回一系列条件假人

Posted

技术标签:

【中文标题】Dask + Pandas:返回一系列条件假人【英文标题】:Dask + Pandas: Returning a sequence of conditional dummies 【发布时间】:2016-11-22 20:08:21 【问题描述】:

在 Pandas 中,如果我想创建一列条件假人(如果变量等于字符串,则为 1,如果不等于,则为 0),那么我在 pandas 中的 goto 是:

data["ebt_dummy"] = np.where((data["paymenttypeid"]=='ebt'), 1, 0)

在 dask 数据帧中天真地尝试此操作会引发错误。遵循 map_partitions 文档中的说明也会引发错误:

data = data.map_partitions(lambda df: df.assign(ebt_dummy = np.where((df["paymenttypeid"]=='ebt'), 1, 0)),  meta='paymenttypeid': 'str', 'ebt_dummy': 'i8')

这样做有什么好方法,或者说最像 Daskthonic 的方法?

【问题讨论】:

【参考方案1】:

这里有一些示例数据可供使用:

In [1]:
df = pd.DataFrame(np.transpose([np.random.choice(['ebt','other'], (10)),
              np.random.rand(10)]), columns=['paymenttypeid','other'])

df

Out[1]:

  paymenttypeid                 other
0         other    0.3130770966143612
1         other    0.5167434068096931
2           ebt    0.7606898392115471
3           ebt    0.9424572692382547
4           ebt     0.624282017575857
5           ebt    0.8584841824784487
6         other    0.5017083765654611
7         other  0.025994123211164233
8           ebt   0.07045354449612984
9           ebt   0.11976351556850084

让我们将其转换为数据框

In [2]: data = dd.from_pandas(df, npartitions=2)

并使用apply(在系列上)分配:

In [3]:
data['ebt_dummy'] = data.paymenttypeid.apply(lambda x: 1 if x =='ebt' else 0, meta=('paymenttypeid', 'str'))
data.compute()

Out [3]:
  paymenttypeid                 other  ebt_dummy
0         other    0.3130770966143612          0
1         other    0.5167434068096931          0
2           ebt    0.7606898392115471          1
3           ebt    0.9424572692382547          1
4           ebt     0.624282017575857          1
5           ebt    0.8584841824784487          1
6         other    0.5017083765654611          0
7         other  0.025994123211164233          0
8           ebt   0.07045354449612984          1
9           ebt   0.11976351556850084          1

更新:

您传递的meta 似乎是问题所在,因为它有效:

data = data.map_partitions(lambda df: df.assign(
                                    ebt_dummy = np.where((df["paymenttypeid"]=='ebt'), 1, 0)))

data.compute()

在我的示例中,如果我想指定 meta,我将不得不传递当前 data 的 dtypes,而不是我期望分配的那个:

data.map_partitions(lambda df: df.assign(
                                    ebt_dummy = np.where((df["paymenttypeid"]=='ebt'), 1, 0)), 
               meta='paymenttypeid': 'str', 'other': 'float64')

【讨论】:

感谢您的回答!有没有一种矢量化的方式来做到这一点?我已经想到了这一点,但是对小数据集以外的任何内容进行逐行应用是非常令人望而却步的 我用map_partitions 更新了我的答案(直到现在才使用Dask...)。我建议你修改你的meta 关键字。以上工作正常。 是的,就是这样。我误解了元数据。感谢您的帮助! 只是为将来偶然发现此问题的任何人提供的最后附录。奇怪的是,与我的第一个批评直接矛盾的是,逐行应用似乎比矢量化方法更快并且使用更少的内存,至少在我的数据测试中是这样。一定是 dask 的一个奇怪的怪癖(或者它可能与减少数据的总副本有关) 我认为这将取决于几个关键因素,包括你的数据有多大,你有什么硬件(如果你想要几十个具有大数据的内核,它可能会花费更多有效),以及您如何配置 dask。此外,如果您在调用 compute 之前执行多个操作,那显然也更好。【参考方案2】:

这也对我有用:

data['ebt_dummy'] = dd.from_array(np.where((df["paymenttypeid"]=='ebt'), 1, 0))

【讨论】:

以上是关于Dask + Pandas:返回一系列条件假人的主要内容,如果未能解决你的问题,请参考以下文章

在 for 循环中将 Python Dask 系列转换为列表或 Dask DataFrame

将Dask包的Pandas DataFrame转换为单个Dask DataFrame

当 Pandas 列中不存在某些类别时获取假人[重复]

如何将假人添加到 Pandas DataFrame?

pandas 返回符合条件单元格所在行

pandas筛选