【问题标题】:Split a data frame using groupby and merge the subsets into columns使用 groupby 拆分数据框并将子集合并到列中
【发布时间】:2014-09-05 17:15:33
【问题描述】:

我有一个大的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 分数名称 0 -0.652909 A 1 0.100885 A 2 0.410907 A 0 0.304012 乙 1 -0.198157 B 2 -0.054764 乙 0 0.358484 C 1 0.616415 C 2 0.389018 C 3 1.164172 C

因此,如果我按列 name 分组,索引是非唯一的,但它是唯一的。我想按名称将数据框拆分为多个小节,然后(通过外部连接)将分数列组装成一个新的大数据框,并将分数的列名更改为相应的组键。我目前拥有的是:

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 南南 1.164172

但似乎不是很pandas-ic。有没有更好的办法?

编辑:根据答案,我进行了一些简单的计时。

%%timeit
df = pandas.DataFrame()
for (key, sub) in test.groupby("name"):
    df = df.join(sub["score"], how="outer")
    df.columns.values[-1] = key
100 次循环,最好的 3 次:每次循环 2.46 毫秒
%%timeit
test.set_index([test.index, "name"]).unstack()
1000 次循环,最好的 3 次:每个循环 1.04 毫秒
%%timeit
test.pivot_table("score", test.index, "name")
100 次循环,最好的 3 次:每次循环 2.54 毫秒

所以unstack 似乎是首选方法。

【问题讨论】:

  • 下一次,您应该提供一个numpy 种子,以便数字与您的预期结果相同。
  • 虽然这个问题并不重要,但感谢@FooBar 的提示。

标签: python pandas merge group-by outer-join


【解决方案1】:

您要查找的函数是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

【讨论】:

  • 只是想为我有 10 M 行的真实数据框添加这一点,此方法将处理时间从 28 分钟缩短到 9.5 秒,谢谢 :)
【解决方案2】:

我最近遇到了一个类似的问题,通过使用 pivot_table 解决了这个问题

    a = """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"""

df = pd.read_csv(StringIO.StringIO(a),sep="\s*")
df = df.pivot_table('score','id','name')


print df

输出:

name         A         B         C
id                                
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

【讨论】:

  • 它可以工作,但unstack 提供了一种更快的方法。谢谢你的回答@ZJS。
  • 尽管 pivot_table 不如 unstack 快,但对于我的 10 M 行的真实数据帧,此方法将处理时间从 28 分钟缩短到可观的 17 秒,谢谢: )
猜你喜欢
  • 1970-01-01
  • 2019-11-08
  • 1970-01-01
  • 2021-01-19
  • 2019-06-20
  • 2018-02-17
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
相关资源
最近更新 更多