Python合并大多数重复的行,将列拆分为其他列

时间:2017-07-26 14:26:09

标签: python pandas

输入数据是dataframe

[
name1 name2 data1  data2
a     x      1      ""
a     y      2      "" 
b     x      3      ""
b     y      4      ""
a     x      5      ""
a     y      6      "" 
b     x      7      ""
b     y      8      ""
]

我想要的是

[
name1 name2 data1  data2
a     x      1      5
a     y      2      6 
b     x      3      7
b     y      4      8
]

对于相同的[name1,name2],将data1移动到data2。我怎么能用python做到这一点?与熊猫? 类似的主题" Python Pandas - 合并大多数重复的行",但我无法找到答案。

2 个答案:

答案 0 :(得分:2)

您可以set_index使用由cumcount创建的列name1Series,然后按unstack重新塑造。

上次重命名列并从reset_index {}创建index列:

df = df.set_index(['name1','name2', df.groupby(['name1','name2']).cumcount()])['data1'] \
       .unstack().rename(columns = lambda x: 'data' + str(x + 1)).reset_index()
print (df)
  name1 name2  data1  data2
0     a     x      1      5
1     a     y      2      6
2     b     x      3      7
3     b     y      4      8

另一个解决方案是创建list,然后通过df构造函数创建新的DataFrame

df1 = df.groupby(['name1','name2'])['data1'].apply(list)
df = pd.DataFrame(df1.values.tolist(), index=df1.index)
df = df.rename(columns = lambda x: 'data' + str(x + 1)).reset_index()
print (df)
  name1 name2  data1  data2
0     a     x      1      5
1     a     y      2      6
2     b     x      3      7
3     b     y      4      8

答案 1 :(得分:1)

选项1
使用defaultdict

from collections import defaultdict

d = defaultdict(list)
[d[(n1, n2)].append(d1) for n1, n2, d1, d2 in df.values];

pd.DataFrame(
    d, [1, 2]
).T.add_prefix('data').rename_axis(['name1', 'name2']).reset_index()

  name1 name2  data1  data2
0     a     x      1      5
1     a     y      2      6
2     b     x      3      7
3     b     y      4      8

选项2
使用numba

from numba import njit

@njit
def plc(f, v):
    m = np.bincount(f).max()
    n = f.max() + 1
    a = np.arange(n * m).reshape(n, m) * 0
    j = np.arange(n) * 0
    for x, y in zip(f, v):
        a[x, j[x]] = y
        j[x] += 1
    return a

f, u = pd.Series(zip(df.name1.values, df.name2.values)).factorize()

new = np.column_stack([np.array(u.tolist()), plc(f, df.data1.values)])

pd.DataFrame(new, columns='name1 name2 data1 data2'.split())

  name1 name2 data1 data2
0     a     x     1     5
1     a     y     2     6
2     b     x     3     7
3     b     y     4     8

<强>时序
小数据

%%timeit
f, u = pd.Series(zip(df.name1.values, df.name2.values)).factorize()

new = np.column_stack([np.array(u.tolist()), plc(f, df.data1.values)])

pd.DataFrame(new, columns='name1 name2 data1 data2'.split())

###############################################################

%%timeit 
d = defaultdict(list)
[d[(n1, n2)].append(d1) for n1, n2, d1, d2 in df.values];

pd.DataFrame(d, [1, 2]).T.add_prefix('data').rename_axis(['name1', 'name2']).reset_index()

###############################################################

%%timeit
df1 = df.groupby(['name1','name2'])['data1'].apply(list)
df2 = pd.DataFrame(df1.values.tolist(), index=df1.index)
df2.rename(columns = lambda x: 'data' + str(x + 1)).reset_index()

#--------------------------------------------------------------

1000 loops, best of 3: 400 µs per loop
100 loops, best of 3: 2.23 ms per loop
100 loops, best of 3: 2.82 ms per loop