Skip to main content
 首页 » 编程设计

python之使用 groupby 拆分数据框并将子集合并到列中

2024年08月27日33bonelee

我有一个很大的 pandas.DataFrame,看起来像这样:

test = pandas.DataFrame({"score": numpy.random.randn(10)}) 
test["name"] = ["A"] * 3 + ["B"] * 3 + ["C"] * 4 
test.index = range(3) + range(3) + range(4) 
id  score       name 
0   -0.652909   A 
1   0.100885    A 
2   0.410907    A 
0   0.304012    B 
1   -0.198157   B 
2   -0.054764   B 
0   0.358484    C 
1   0.616415    C 
2   0.389018    C 
3   1.164172    C 

So the index is non-unique but is unique if I group by the column name. I would like to split the data frame into subsections by name and then assemble (by means of an outer join) the score columns into one big new data frame and change the column names of the scores to the respective group key. What I have at the moment is:

df = pandas.DataFrame() 
for (key, sub) in test.groupby("name"): 
    df = df.join(sub["score"], how="outer") 
    df.columns.values[-1] = key 

这会产生预期的结果:

id  A           B           C 
0   -0.652909   0.304012    0.358484 
1   0.100885    -0.198157   0.616415 
2   0.410907    -0.054764   0.389018 
3   NaN         NaN         1.164172 

but seems not very pandas-ic. Is there a better way?

Edit: Based on the answers I ran some simple timings.

%%timeit 
df = pandas.DataFrame() 
for (key, sub) in test.groupby("name"): 
    df = df.join(sub["score"], how="outer") 
    df.columns.values[-1] = key 
100 loops, best of 3: 2.46 ms per loop
%%timeit 
test.set_index([test.index, "name"]).unstack() 
1000 loops, best of 3: 1.04 ms per loop
%%timeit 
test.pivot_table("score", test.index, "name") 
100 loops, best of 3: 2.54 ms per loop

所以 unstack 似乎是首选方法。

请您参考如下方法:

您要查找的函数是unstack .为了让 pandas 知道要拆栈的目的,我们将首先创建一个 MultiIndex,我们将列添加为 last 索引。 unstack() 然后将基于最后一个索引层取消堆叠(默认情况下),因此我们得到您想要的:

In[152]: test = pandas.DataFrame({"score": numpy.random.randn(10)}) 
test["name"] = ["A"] * 3 + ["B"] * 3 + ["C"] * 4 
test.index = range(3) + range(3) + range(4) 
In[153]: test 
Out[153]:  
      score name 
0 -0.208392    A 
1 -0.103659    A 
2  1.645287    A 
0  0.119709    B 
1 -0.047639    B 
2 -0.479155    B 
0 -0.415372    C 
1 -1.390416    C 
2 -0.384158    C 
3 -1.328278    C 
In[154]: test.set_index([index, 'name'], inplace=True) 
test.unstack() 
Out[154]:  
         score                     
name         A         B         C 
0    -0.208392  0.119709 -0.415372 
1    -0.103659 -0.047639 -1.390416 
2     1.645287 -0.479155 -0.384158 
3          NaN       NaN -1.328278