我有一个这样的数据表(忽略索引):
group, subgroup, score
A, B, 0
A, C, 1.5
A, A, 5
B, A, 1
B, F, 1.5
B, C, 0
C, C, 2
C, D, 3
我想要一张这样的桌子:
group, subgroup w lowest score, w second lowest score, w third lowest
A, B, C, A
B, C, A, F
C, C, D, (blank)
我如何使用Pandas从一个到另一个?
答案 0 :(得分:2)
一种方法是引入一个对子组进行排名然后再进行调整的列。 首先按分数排序并按变换进行分组:
df.sort('score', inplace=True)
ranks = ['lowest', 'second lowest', 'third lowest']
df['rank'] = df.groupby('group').subgroup.transform(lambda s: ranks[:len(s)])
然后转动:
In [44]: df.pivot(index='group', columns='rank', values='subgroup')
Out[44]:
rank lowest second lowest third lowest
group
A B C A
B C A F
C C D NaN
答案 1 :(得分:2)
这是一种非常紧凑的方式。为了简单起见,我用排名写了“得分”值,但是如果你愿意的话,你可以保留原来的分数(这只是一点点冗长)。
df['score'] = df.groupby('group')['score'].rank()
df.set_index(['group','score']).unstack()
subgroup
score 1 2 3
group
A B C A
B C A F
C C D NaN
请注意,这会阻塞第一个或第二个存在平局的数据。你可以通过各种方式解决这个问题(例如,rank(method='first')
是单向的,但rank
也为你提供了其他选项)。你没有指定,所以我不确定你想怎么处理它。
编辑添加:现在我正在更仔细地查看@ JoeCondron的答案我发现我的方法非常相似,但我认为它们的不同之处我会留下一点点至少。特别是乔正在排序,我的排名在你如何处理平局时可能很重要。
答案 2 :(得分:1)
由于可能存在没有“第三低分”的情况,我们可能需要itertools.izip_longest
:
In [85]:
from itertools import izip_longest
gby = df.groupby(['group']).agg(lambda x: tuple(x))
print pd.DataFrame(data = list(izip_longest(*map(lambda x, y: [v[1] for v in sorted(zip(y,x))],
gby.subgroup, gby.score))),
columns= gby.index,
index = ['subgroup w lowest score',
'w second lowest score',
'w third lowest']).T
subgroup w lowest score w second lowest score w third lowest
group
A B C A
B C A F
C C D None