2017-07-08 55 views
2

我面臨的問題是,將列的值聚集在一起並保留其他列的各個值。我想做類似這樣的事情:grouping rows in list in pandas groupby如何按列分組,並將其他列的值作爲熊貓列表返回?

但是,我希望列表/字典(最好是後者)包含多個列的值。 示例有關此數據框:

DF:

Col1 Col2 Col3 
A  xyz  1 
A  pqr  2 
B  xyz  2 
B  pqr  3 
B  lmn  1 
C  pqr  2 

我想要的東西,喜歡 -

A {'xyz':1, 'pqr': 2} 
B {'xyz':2, 'pqr': 3, 'lmn': 1} 
C {'pqr':2} 

我試圖做

df.groupby('Col1')[['Col2', 'Col3']].apply(list) 

這是中提到的解決方案的一個變種鏈接的帖子,但沒有給我我需要的結果。

從那天起,我也想將其轉變爲形式的數據幀這一點:

xyz pqr lmn 
A 1 2 NaN 
B 2 3 1 
C NaN 2 NaN 

回答

1

使用pivotunstack

df = df.pivot(index='Col1',columns='Col2',values='Col3') 
print (df) 
Col2 lmn pqr xyz 
Col1    
A  NaN 2.0 1.0 
B  1.0 3.0 2.0 
C  NaN 2.0 NaN 

df = df.set_index(['Col1','Col2'])['Col3'].unstack() 
print (df) 

Col2 lmn pqr xyz 
Col1    
A  NaN 2.0 1.0 
B  1.0 3.0 2.0 
C  NaN 2.0 NaN 

但如果:

ValueError: Index contains duplicate entries, cannot reshape

這意味着重複,需要pivot_table或聚集體groupbymean(可改爲summedian),和最後重塑通過unstack

print (df) 
    Col1 Col2 Col3 
0 A xyz  1 <-same A, xyz 
1 A xyz  5 <-same A, xyz 
2 A pqr  2 
3 B xyz  2 
4 B pqr  3 
5 B lmn  1 
6 C pqr  2 

df = df.groupby(['Col1','Col2'])['Col3'].mean().unstack() 
print (df) 
Col2 lmn pqr xyz 
Col1    
A  NaN 2.0 3.0 (1+5)/2 = 3 
B  1.0 3.0 2.0 
C  NaN 2.0 NaN 

編輯:

對於檢查由Col1Col2所有重複:

print (df[df.duplicated(subset=['Col1','Col2'], keep=False)]) 
    Col1 Col2 Col3 
0 A xyz  1 
1 A xyz  5 

EDIT1:

如果只需要第一行,如果重複:

df = df.groupby(['Col1','Col2'])['Col3'].first().unstack() 
print (df) 
Col2 lmn pqr xyz 
Col1    
A  NaN 2.0 1.0 
B  1.0 3.0 2.0 
C  NaN 2.0 NaN 

或者更好的第一通過drop_duplicates刪除重複,然後使用第一或第二溶液:

df = df.drop_duplicates(subset=['Col1','Col2']) 
df = df.pivot(index='Col1',columns='Col2',values='Col3') 
print (df) 
Col2 lmn pqr xyz 
Col1    
A  NaN 2.0 1.0 
B  1.0 3.0 2.0 
C  NaN 2.0 NaN 
+0

必須重複,因爲錯誤。最後一個。我添加了檢查它的代碼。 – jezrael

+0

謝謝!我得到了ValueError。但是,我不能使用您提到的平均方法,因爲這些值是分類變量。有什麼辦法可以使用它遇到的第一行(例如忽略行A,xyz,5)? – Melsauce

+0

查看編輯答案。 – jezrael

1

你到底想要什麼是數據透視表。

df.pivot_table(index='Col1',columns='Col2',values='Col3')

查找的文檔,更多的選擇。

+0

我在我的數據集上運行時遇到了這個問題:ValueError:索引包含重複條目,無法重塑 – Melsauce

1

這些都不是一個僅pandas解決方案。我提供了他們,因爲我發現探索替代品有趣。 bincount基礎解決方案速度非常快,但透明度較差。

創造性的解決方案1 ​​
collections.defaultdict和字典解析

from collections import defaultdict 

d = defaultdict(dict) 
[d[c2].setdefault(c1, c3) for i, c1, c2, c3 in df.itertuples()]; 
pd.DataFrame(d) 

    lmn pqr xyz 
A NaN 2 1.0 
B 1.0 3 2.0 
C NaN 2 NaN 

創造性的解決方案2
pd.factorizenp.bincount

f1, u1 = pd.factorize(df.Col1.values) 
f2, u2 = pd.factorize(df.Col2.values) 
w = df.Col3.values 

n, m = u1.size, u2.size 

v = np.bincount(f1 * n + f2, w, n * m).reshape(n, m) 
pd.DataFrame(np.ma.array(v, mask=v == 0), u1, u2) 

    lmn pqr xyz 
A NaN 2 1.0 
B 1.0 3 2.0 
C NaN 2 NaN 

時序

%timeit df.pivot(index='Col1',columns='Col2',values='Col3') 
%timeit df.set_index(['Col1','Col2'])['Col3'].unstack() 
%timeit df.groupby(['Col1','Col2'])['Col3'].mean().unstack() 
%timeit df.pivot_table(index='Col1',columns='Col2',values='Col3') 

%%timeit 
d = defaultdict(dict) 
[d[c2].setdefault(c1, c3) for i, c1, c2, c3 in df.itertuples()]; 
pd.DataFrame(d) 

%%timeit 
f1, u1 = pd.factorize(df.Col1.values) 
f2, u2 = pd.factorize(df.Col2.values) 
w = df.Col3.values 

n, m = u1.size, u2.size 

v = np.bincount(f1 * n + f2, w, n * m).reshape(n, m) 
pd.DataFrame(np.ma.array(v, mask=v == 0), u1, u2) 

小數據

1000 loops, best of 3: 1.11 ms per loop 
1000 loops, best of 3: 1.67 ms per loop 
1000 loops, best of 3: 1.51 ms per loop 
100 loops, best of 3: 4.17 ms per loop 

1000 loops, best of 3: 1.18 ms per loop 

1000 loops, best of 3: 420 µs per loop 

介質數據

from string import ascii_letters 
l = list(ascii_letters) 
df = pd.DataFrame(dict(
     Col1=np.random.choice(l, 10000), 
     Col2=np.random.choice(l, 10000), 
     Col3=np.random.randint(10, size=10000) 
    )).drop_duplicates(['Col1', 'Col2']) 

1000 loops, best of 3: 1.75 ms per loop 
100 loops, best of 3: 2.17 ms per loop 
100 loops, best of 3: 2.2 ms per loop 
100 loops, best of 3: 4.89 ms per loop 

100 loops, best of 3: 5.6 ms per loop 

1000 loops, best of 3: 549 µs per loop 
+0

這真棒@piRSquared!只有一個小指針:我不能/不應該計算Col3的均值,因爲它是一個分類變量。 – Melsauce

+0

@RijulMagu假設你的組合Col1和Col2是唯一的,這不是問題。但是,如果它們不是唯一的,那麼您最喜歡聚合多個實例?您必須決定您的最終數據框由每個「Col1」和「Col2」的唯一組合組成的單元組成。該單元必須包含所有可能實例的彙總或彙總。你想要最後一個?,第一個? – piRSquared

+0

不幸的是,沒有一個好的方法可以決定(在原始數據集中,出現重複的地方,一個是「正確的」行,另一個是僞造的,但很難分辨哪個是哪個)。因此,我正在使用第一個。 – Melsauce

相關問題