2013-07-24 16 views
48

我有这样一个数据帧:熊猫GROUPBY:如何得到字符串的工会

A   B  C 
0 1 0.749065 This 
1 2 0.301084  is 
2 3 0.463468  a 
3 4 0.643961 random 
4 1 0.866521 string 
5 2 0.120737  ! 

调用

In [10]: print df.groupby("A")["B"].sum() 

将返回

A 
1 1.615586 
2 0.421821 
3 0.463468 
4 0.643961 

现在我想这样做“C”栏的“相同”。由于该列包含字符串,sum()不起作用(尽管您可能认为它会连接字符串)。我真的想看到的是一个列表或设置字符串各组,即

A 
1 {This, string} 
2 {is, !} 
3 {a} 
4 {random} 

我一直在想办法做到这一点。

Series.unique()(http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.unique.html)不工作,虽然

df.groupby("A")["B"] 

pandas.core.groupby.SeriesGroupBy object 

,所以我希望任何系列的方法是可行的。有任何想法吗?

回答

92
In [4]: df = read_csv(StringIO(data),sep='\s+') 

In [5]: df 
Out[5]: 
    A   B  C 
0 1 0.749065 This 
1 2 0.301084  is 
2 3 0.463468  a 
3 4 0.643961 random 
4 1 0.866521 string 
5 2 0.120737  ! 

In [6]: df.dtypes 
Out[6]: 
A  int64 
B float64 
C  object 
dtype: object 

当您应用自己的函数时,不会自动排除非数字列。这会慢一些,但是,比.sum()应用到groupby

In [8]: df.groupby('A').apply(lambda x: x.sum()) 
Out[8]: 
    A   B   C 
A       
1 2 1.615586 Thisstring 
2 4 0.421821   is! 
3 3 0.463468   a 
4 4 0.643961  random 

sum默认会连接

In [9]: df.groupby('A')['C'].apply(lambda x: x.sum()) 
Out[9]: 
A 
1 Thisstring 
2   is! 
3    a 
4  random 
dtype: object 

你可以做很多你想

In [11]: df.groupby('A')['C'].apply(lambda x: "{%s}" % ', '.join(x)) 
Out[11]: 
A 
1 {This, string} 
2   {is, !} 
3    {a} 
4   {random} 
dtype: object 

这样做一个什么整个帧组。关键是要返回Series

def f(x): 
    return Series(dict(A = x['A'].sum(), 
         B = x['B'].sum(), 
         C = "{%s}" % ', '.join(x['C']))) 

In [14]: df.groupby('A').apply(f) 
Out[14]: 
    A   B    C 
A        
1 2 1.615586 {This, string} 
2 4 0.421821   {is, !} 
3 3 0.463468    {a} 
4 4 0.643961  {random} 
+0

感谢杰夫。我怎样才能一次性在多个列上应用不同的功能,例如求和列“B”并设置在“C”列? – Anne

+0

增加了一个部分来做到这一点 – Jeff

+1

谢谢杰夫!还没有放弃它,但想了解它背后的逻辑。你正在创建一个系列字典,并把它变成一个系列?无法让我的(被蒙蔽的)大脑围绕甚至意味着什么......你是否介意再详述一下?并且在'A = x ['A']。sum()'中,是第一个A对象还是字符串?如果它是一个字符串,它不应该有引号吗?对不起,正如我所说的,非常疲惫,我希望我的意思是... – Anne

28

可以使用apply方法来任意函数应用于分组数据。所以如果你想要一套,请申请set。如果你想要一个列表,请应用list

>>> d 
    A  B 
0 1 This 
1 2  is 
2 3  a 
3 4 random 
4 1 string 
5 2  ! 
>>> d.groupby('A')['B'].apply(list) 
A 
1 [This, string] 
2   [is, !] 
3    [a] 
4   [random] 
dtype: object 

如果你想要别的东西,只写一个函数,你想要做什么,然后apply这一点。

7

您可以使用aggregate(或agg)函数来连接值。 (未测试的代码)

​​
1

一个简单的解决办法是:

>>> df.groupby(['A','B']).c.unique().reset_index()