我遇到麻烦,将列的值聚合在一起并保留其他列的相应值。我想做类似的事情: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
答案 0 :(得分:1)
最终你想要的是一个数据透视表。
df.pivot_table(index='Col1',columns='Col2',values='Col3')
查看文档以获取更多选项。
答案 1 :(得分:1)
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:索引包含重复的条目,无法重塑
表示重复,需要pivot_table
或groupby
与mean
汇总(可以更改为sum
,median
),最后重新设置为{ {1}}:
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
和Col1
检查所有重复项:
Col2
EDIT1:
如果重复需要第一行:
print (df[df.duplicated(subset=['Col1','Col2'], keep=False)])
Col1 Col2 Col3
0 A xyz 1
1 A xyz 5
或者最好先按drop_duplicates
删除重复项,然后使用第一个或第二个解决方案:
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
答案 2 :(得分: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.factorize
和np.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