![](/img/trans.png)
[英]Pandas - Check if value from a column exists in any index of a MultiIndex dataframe
[英]Pandas MultiIndex DataFrame reference index value in column calculation
我想在某些計算中有效地使用來自 DataFrame 的 MultiIndex 的值。 例如,從以下開始:
np.random.seed(456)
j = [(a, b) for a in ['A','B','C'] for b in random.sample(pd.date_range('2017-01-01', periods=50, freq='W').tolist(), 5)]
i = pd.MultiIndex.from_tuples(j, names=['Name','Num'])
df = pd.DataFrame(np.random.randn(15), i, columns=['Vals'])
df['SmallestNum'] = df.reset_index(level=1).groupby('Name')['Num'].transform('min').values
假設我想計算一個新列Diff = Num - SmallestNum
。 一種有效但我認為笨拙的方法是將我想要引用的索引級別復制到真正的列中,然后進行區別:
df['NumCol'] = df.index.get_level_values(1)
df['Diff'] = df['NumCol'] - df['SmallestNum']
但是如果我這樣做,我覺得我仍然不理解使用 DataFrames 的正確方法。 我認為“正確”的解決方案類似於以下任一解決方案,它們不會創建和存儲索引值的完整副本:
df['Diff'] = df.transform(lambda x: x.index.get_level_values(1) - x['SmallestNum'])
df['Diff'] = df.reset_index(level=1).apply(lambda x: x['Num'] - x['SmallestNum'])
...然而,不僅這些表達式都不起作用*,而且我的理解是,像.transform
或.apply
這樣的 DataFrame 操作.transform
對顯式“矢量化”行引用進行操作的操作慢得多。
那么在這個例子中為新的Diff
列編寫計算的“正確和有效”的方法是什么?
*更新:這個問題因索引級別 1 值不唯一這一事實(可能是錯誤)而變得更加復雜,這會導致在索引值唯一時起作用的公式因NotImplementedError: Index._join_level on non-unique index is not implemented
。 幸運的是jezrael 的答案包含的解決方法似乎與顯式矢量化計算一樣有效。
我認為你只需要減去:
df['Diff'] = df.index.get_level_values(1) - df['SmallestNum']
print (df)
Vals SmallestNum Diff
Name Num
A 28 1.180140 28 0
44 0.984257 28 16
90 1.835646 28 62
43 -1.886823 28 15
29 0.424763 28 1
B 80 -0.433105 38 42
61 -0.166838 38 23
46 0.754634 38 8
38 1.966975 38 0
93 0.200671 38 55
C 40 0.742752 12 28
82 -1.264271 12 70
12 -0.112787 12 0
78 0.667358 12 66
70 0.357900 12 58
編輯:對於第二級工作中的非唯一DatetimeIndex
減去由values
創建的 numpy 數組:
np.random.seed(456)
a = pd.date_range('2015-01-01', periods=6).values
j = [['A'] * 5 + ['B'] * 5 + ['C'] * 5, pd.to_datetime(np.random.choice(a, size=15))]
i = pd.MultiIndex.from_arrays(j, names=['Name','Num'])
df = pd.DataFrame(np.random.randn(15), i, columns=['Vals'])
df['SmallestNum'] = df.reset_index(level=1).groupby('Name')['Num'].transform('min').values
df['Diff'] = df.index.get_level_values(1).values - df['SmallestNum'].values
print (df)
Vals SmallestNum Diff
Name Num
A 2015-01-04 -1.842419 2015-01-02 2 days
2015-01-06 -0.786788 2015-01-02 4 days
2015-01-04 1.180140 2015-01-02 2 days
2015-01-02 0.984257 2015-01-02 0 days
2015-01-03 1.835646 2015-01-02 1 days
B 2015-01-05 -1.886823 2015-01-03 2 days
2015-01-03 0.424763 2015-01-03 0 days
2015-01-05 -0.433105 2015-01-03 2 days
2015-01-06 -0.166838 2015-01-03 3 days
2015-01-05 0.754634 2015-01-03 2 days
C 2015-01-06 1.966975 2015-01-02 4 days
2015-01-06 0.200671 2015-01-02 4 days
2015-01-05 0.742752 2015-01-02 3 days
2015-01-02 -1.264271 2015-01-02 0 days
2015-01-04 -0.112787 2015-01-02 2 days
另一種解決方案:
df['Diff'] = (df.reset_index(level=1)
.groupby('Name')['Num']
.transform(lambda x: x - x.min())
.values)
print (df)
Vals Diff
Name Num
A 2015-01-04 -1.842419 2 days
2015-01-06 -0.786788 4 days
2015-01-04 1.180140 2 days
2015-01-02 0.984257 0 days
2015-01-03 1.835646 1 days
B 2015-01-05 -1.886823 2 days
2015-01-03 0.424763 0 days
2015-01-05 -0.433105 2 days
2015-01-06 -0.166838 3 days
2015-01-05 0.754634 2 days
C 2015-01-06 1.966975 4 days
2015-01-06 0.200671 4 days
2015-01-05 0.742752 3 days
2015-01-02 -1.264271 0 days
2015-01-04 -0.112787 2 days
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.