【问题标题】:python dask dataframes - concatenate groupby.apply output to a single data framepython dask dataframes - 将 groupby.apply 输出连接到单个数据帧
【发布时间】:2018-04-23 07:34:44
【问题描述】:

我正在使用 dask dataframe.groupby().apply() 并获得一个 dask 系列作为返回值。 我是每个组的一个列表三元组,例如 (a,b,1),然后希望将所有三元组变成一个单独的 dask 数据帧

我在映射函数的末尾使用此代码将三元组作为 dask df 返回

#assume here that trips is a generator for tripletes such as you would produce from itertools.product([l1,l2,l3])
trip = list(itertools.chain.from_iterable(trip))
df = pd.DataFrame.from_records(trip)
return dd.from_pandas(df,npartitions=1)

然后当我尝试使用类似于pandas concatdask concatenate

假设apply函数的结果是变量result。 我正在尝试使用 将 dask.dataframe 导入为 dd dd.concat(结果,轴=0

并得到错误

raise TypeError("dfs 必须是 DataFrames/Series 对象的列表") TypeError: dfs 必须是 DataFrames/Series 对象的列表

但是当我使用

检查结果类型时
print type(result)

我明白了

输出:类 'dask.dataframe.core.Series'

在一组 dask groupby 对象上应用函数并将所有结果放入一个数据帧的正确方法是什么?

谢谢

编辑:------------------------------ ----------------- 为了产生用例,假设这个假数据生成

import random
import pandas as pd
import dask.dataframe as dd
people = [[random.randint(1,3), random.randint(1,3), random.randint(1,3)] for i in range(1000)]
ddf = dd.from_pandas(pd.DataFrame.from_records(people, columns=["first name", "last name", "cars"]), npartitions=1)

现在我的任务是按名字和姓氏对人进行分组(例如,所有具有相同名字和名字的人),然后我需要获取一个新的 dask 数据框,其中将包含每个组有多少辆车。

假设 apply 函数可以返回一系列元组列表,例如 [(name,name,cars count),(name,name,cars count)] 或具有相同列的数据框 - name, name,车数。

是的,我知道可以通过其他方式解决特定用例,但请相信我,我的用例更复杂。但我不能共享数据,也不能生成任何类似的数据。所以让我们使用一个虚拟数据:-)

挑战是将应用的所有结果连接到单个 dask 数据帧中(pandas 数据帧将是一个问题,数据将不适合内存 - 因此通过 pandas 数据帧进行转换将是一个问题)

【问题讨论】:

  • 您的函数的输出似乎是Series,所以concat 不是必需的。如果得到MultiIndex,那么reset_index 应该对DataFrame 有帮助,比如dataframe.groupby().apply(func).reset_index()
  • @jezrael 当我尝试使用 result.reset_index().compute() 我得到 - 引发 NotImplementedError()。我在这里错过了什么?
  • 你能用输入数据和输出创建来mcve吗?没有数据很难找到解决方案。
  • 谢谢,你的功能在第一个代码段落中,只需要def(func):
  • @jezrael - 谢谢!这是函数的相关代码,我很清楚python语法要求:-)为了适合我的真实数据,真实代码要复杂得多,这是虚拟数据的相关部分。

标签: python pandas dataframe apply dask


【解决方案1】:

供您编辑:

In [8]: ddf.groupby(['first name', 'last name']).cars.count().compute()
Out[8]:
first name  last name
1           1            107
            2            107
            3            110
2           1            117
            2            120
            3             99
3           1            119
            2            103
            3            118
Name: cars, dtype: int64

【讨论】:

  • 您能否解释一下它是如何将一系列由 map 创建的 dask 数据帧或应用程序而不用 pandas 炸毁内存的?
  • “一系列 dask 数据帧”是什么意思?我在您的示例中没有看到任何关于此的内容。您能否更新您的问题以更清楚?
【解决方案2】:

如果apply 的输出是pandas DataFrame,对我来说工作,所以如果需要,最后转换为dask DataFrame

def f(x):
    trip = ((1,2,x) for x in range(3))
    df = pd.DataFrame.from_records(trip)
    return df

df1 = ddf.groupby('cars').apply(f, meta={'x': 'i8', 'y': 'i8', 'z': 'i8'}).compute()
#only for remove MultiIndex
df1 = df1.reset_index()
print (df1)
   cars  level_1  x  y  z
0     1        0  1  2  0
1     1        1  1  2  1
2     1        2  1  2  2
3     2        0  1  2  0
4     2        1  1  2  1
5     2        2  1  2  2
6     3        0  1  2  0
7     3        1  1  2  1
8     3        2  1  2  2

ddf1 = dd.from_pandas(df1,npartitions=1)
print (ddf1)
                cars level_1      x      y      z
npartitions=1                                    
0              int64   int64  int64  int64  int64
8                ...     ...    ...    ...    ...
Dask Name: from_pandas, 1 tasks

编辑:

L = []
def f(x):
    trip = ((1,2,x) for x in range(3))
    #append each
    L.append(da.from_array(np.array(list(trip)), chunks=(1,3)))

ddf.groupby('cars').apply(f, meta={'x': 'i8', 'y': 'i8', 'z': 'i8'}).compute()
dar =  da.concatenate(L, axis=0)
print (dar)
dask.array<concatenate, shape=(12, 3), dtype=int32, chunksize=(1, 3)>

【讨论】:

  • 成功了!惊人的!我觉得主要的区别是你给它的差异元,它成功了,还有一个小问题,由于内存限制,我无法转换为 pd 数据帧,我怎样才能删除多索引而不做所以呢?
  • 在 pandas 中使用 group_keys=Falsegroupby 中,在 dask 中不确定它是否工作......
  • 我找不到任何关于它是否已经在工作的参考资料,想说明一下吗?
  • 给我一些时间,我去测试一下。
  • 不,不幸的是,这在 dask 中没有实现 :(
猜你喜欢
  • 2016-10-28
  • 2017-10-04
  • 1970-01-01
  • 2020-02-18
  • 1970-01-01
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 2019-05-12
相关资源
最近更新 更多