python dask dataframes - 将groupby.apply输出连接到单个数据框

时间:2017-11-10 06:04:06

标签: python pandas dataframe apply dask

我正在使用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 concat

类似的dask concatenate

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

并获得错误

  

引发TypeError(“dfs必须是DataFrames / Series对象的列表”)   TypeError:dfs必须是DataFrames / Series对象的列表

但是当我使用

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

我得到了

  

输出:class'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)

现在我的任务是按名字和姓氏对人进行分组(例如,所有名字和姓氏相同的人),而且我需要获得一个新的数据库,其中包含每组有多少辆汽车

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

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

挑战是将apply的所有结果连接到单个dask数据帧(pandas数据帧在这里将是一个问题,数据将不适合存储器 - 因此通过pandas数据帧的转换将是一个问题)< / p>

2 个答案:

答案 0 :(得分: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)>

答案 1 :(得分:2)

为了您的编辑:

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