引用DataFrame的MultiIndex值不正确?

时间:2018-02-24 21:46:06

标签: python pandas dataframe multi-index

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值的NameColNumCol列副本的情况下执行此操作?

2 个答案:

答案 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