2017-09-26 85 views
2

行,我有一個DF重塑列成組地使用熊貓

id name value 
1  abc  10 
1  qwe  23 
1  zxc  12 
2  sdf  10 
2  wed  23 
2  abc  12 
2  mnb  11 

我想這個數據幀重塑成:

id n1 n2 n3 n4 
1 abc qwe zxc 0 
2 sdf wed abc mnb 

我們可以看到,有3行中的id = 1和4行id = 2。因此,用這個事件替換最後一列n4 = 0。

這是測試數據幀,有可能發生的是,對於一個ID可能有1-2行了。

它是像我們做的R - dcast。 我們如何在熊貓中做到這一點?

回答

1

您可以使用set_indexcumcount每團體計數新列的名稱和unstack重塑,最後重命名列:

df = (df.set_index(['id', df.groupby('id').cumcount()])['name'] 
     .unstack(fill_value=0) 
     .rename(columns = lambda x: 'n{}'.format(x + 1)) 
     .reset_index()) 
print (df) 
    id n1 n2 n3 n4 
0 1 abc qwe zxc 0 
1 2 sdf wed abc mnb 

DataFrame構造解決方案,是必要的沒有NaN值以原始數據:

df1 = df.groupby('id')['name'].apply(list) 
print (df1) 
id 
1   [abc, qwe, zxc] 
2 [sdf, wed, abc, mnb] 
Name: name, dtype: object 

df = (pd.DataFrame(df1.values.tolist(), index=df1.index) 
     .fillna(0) 
     .rename(columns = lambda x: 'n{}'.format(x + 1)) 
     .reset_index()) 
print (df) 
    id n1 n2 n3 n4 
0 1 abc qwe zxc 0 
1 2 sdf wed abc mnb 

和解決方案與GroupBy.applySeries構造:

df1 = (df.groupby('id')['name'].apply(lambda x: pd.Series(x.values, index=range(1,len(x)+1))) 
     .unstack(fill_value=0) 
     .add_prefix('n') 
     .reset_index()) 
print (df1) 

    id n1 n2 n3 n4 
0 1 abc qwe zxc 0 
1 2 sdf wed abc mnb 
2

可能矯枉過正

f, u = pd.factorize(df.id.values) 
b = np.bincount(f) 
n, m = u.size, b.max() 
c = np.arange(f.size) - np.arange(n).repeat(b) * (m - 1) 

v = np.zeros((n, m), dtype=object) 
v[f, c] = df.name.values 

pd.DataFrame(
    v, pd.Index(u, name='id'), 
    ['n{}'.format(i) for i in range(1, m + 1)] 
).reset_index() 

    id n1 n2 n3 n4 
0 1 abc qwe zxc 0 
1 2 sdf wed abc mnb 
2

你可以去str路線和使用groupby後一些正則表達式替換和分裂。

df.groupby('id').name.apply(lambda x: str(list(x)))\ 
      .str.replace("[\[\],']", "")\ 
      .str.split(expand=True).fillna(0)\ 
      .rename(columns = lambda x: 'n{}'.format(x + 1)) 

    n1 n2 n3 n4 
id      
1 abc qwe zxc 0 
2 sdf wed abc mnb 
1

通過使用dfply包就可以做到如R的dcast

# for Python3 only 
pip install dfply 

使用的dfplyspread功能。

import pandas as pd 
from io import StringIO 
from dfply import * 

csv = StringIO("""id,name,value 
1,abc,10 
1,qwe,23 
1,zxc,12 
2,sdf,10 
2,wed,23 
2,abc,12 
2,mnb,11""") 
df = pd.read_csv(csv) 

df['sequence'] = df.groupby('id').cumcount() 
df = df[["id", "sequence", "name"]] >> spread(X.sequence, X.name) 
df = df.set_index("id").fillna(0).rename(columns = lambda x: 'n{}'.format(x + 1)).reset_index() 
print(df) 
# id n1 n2 n3 n4 
# 0 1 abc qwe zxc 0 
# 1 2 sdf wed abc mnb