Pandas似乎拒绝使用DataFrame索引值的努力,就像它们是列值一样。因此,我经常将它们复制到一列中,以便我可以引用它们进行计算。这是一个好习惯吗?或者我错过了引用索引值的“正确”方法?
考虑以下示例:
j = [(a, b) for a in ['A','B','C'] for b in random.sample(range(1, 100), 5)]
i = pd.MultiIndex.from_tuples(j, names=['Name','Num'])
df = pd.DataFrame(np.random.randn(15), i, columns=['Vals'])
现在假设我想在DataFrame中添加一列'SmallestNum'
,列出每个关联索引Num
的最小索引Name
。
目前,我能找到让这个工作的唯一方法(假设MultiIndex很大而我没有像元组一样方便)是:
首先:将两个索引级别复制到DataFrame的列中:
df['NameCol'] = df.index.get_level_values(0)
df['NumCol'] = df.index.get_level_values(1)
否则,我无法弄清楚如何获得每个Num
的最小Name
值。至少现在我可以通过:
smallest = pd.DataFrame(df.groupby(['Name'])['NumCol'].min())
最后,我可以将这些数据作为新列合并回DataFrame,但这只是因为我可以引用NameCol
:
df.merge(smallest.rename(columns={'NumCol' : 'SmallestNum'}), how='left', right_index=True, left_on=['NameCol'])
那么有没有办法在不创建MultiIndex值的NameCol
和NumCol
列副本的情况下执行此操作?
答案 0 :(得分:1)
这有效:
## get smallest values per Name
vals = df.reset_index(level=1).groupby('Name')['Num'].min()
## map the values to df
df['SmallestNum'] = pd.Series(df.index.get_level_values(0)).map(vals).values
答案 1 :(得分:1)
您可以使用transform
:
np.random.seed(456)
j = [(a, b) for a in ['A','B','C'] for b in np.random.randint(1, 100, size=5)]
i = pd.MultiIndex.from_tuples(j, names=['Name','Num'])
df = pd.DataFrame(np.random.randn(15), i, columns=['Vals'])
print (df)
Vals
Name Num
A 28 1.180140
44 0.984257
90 1.835646
43 -1.886823
29 0.424763
B 80 -0.433105
61 -0.166838
46 0.754634
38 1.966975
93 0.200671
C 40 0.742752
82 -1.264271
12 -0.112787
78 0.667358
70 0.357900
df['SmallestNum'] = df.reset_index(level=1).groupby('Name')['Num'].transform('min').values
或者:
df['SmallestNum'] = df.groupby('Name').transform(lambda x: x.index.get_level_values(1).min())
print (df)
Vals SmallestNum
Name Num
A 28 1.180140 28
44 0.984257 28
90 1.835646 28
43 -1.886823 28
29 0.424763 28
B 80 -0.433105 38
61 -0.166838 38
46 0.754634 38
38 1.966975 38
93 0.200671 38
C 40 0.742752 12
82 -1.264271 12
12 -0.112787 12
78 0.667358 12
70 0.357900 12