2013-07-24 14 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()