[英]Multiply all columns of a multi-indexed DataFrame by appropriate values in a Series
[英]Mask dataframe with another multi-indexed Series
我有一個數據框,我想用多索引系列的布爾值掩蓋(轉換為NaN),其中該系列的多索引也是該數據框中的列名。 例如,如果df
為:
df = pd.DataFrame({ 'A': (188, 750, 1330, 1385, 188, 750, 810, 1330, 1385),
'B': (1, 2, 4, 5, 1, 2, 3, 4, 5),
'C': (2, 5, 7, 2, 5, 5, 3, 7, 2),
'D': ('foo', 'foo', 'foo', 'foo', 'bar', 'bar', 'bar', 'bar', 'bar') })
A B C D
0 188 1 2 foo
1 750 2 5 foo
2 1330 4 7 foo
3 1385 5 2 foo
4 188 1 5 bar
5 750 2 5 bar
6 810 3 3 bar
7 1330 4 7 bar
8 1385 5 2 bar
而多索引系列ser
為:
arrays = [('188', '750', '810', '1330', '1385'),
('1', '2', '3', '4', '5')]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['A', 'B'])
ser = pd.Series([False, False, True, False, True], index=index)
A B
188 1 False
750 2 False
810 3 True
1330 4 False
1385 5 True
dtype: bool
我怎么能掩蓋(轉換為NAN)在列的值C
在df
,其中的條目是False
的系列ser
,以結束與最后的數據幀,將是這樣的:
A B C D
0 188 1 2 foo
1 750 2 5 foo
2 1330 4 7 foo
3 1385 5 NaN foo
4 188 1 5 bar
5 750 2 5 bar
6 810 3 NaN bar
7 1330 4 7 bar
8 1385 5 NaN bar
更改ser
的初始化步驟:
arrays = [('188', '750', '810', '1330', '1385'),
('1', '2', '3', '4', '5')]
# Note: The change is in this step - make the levels numeric.
tuples = list(zip(*map(pd.to_numeric, arrays)))
index = pd.MultiIndex.from_tuples(tuples, names=['A', 'B'])
ser = pd.Series([False, False, True, False, True], index=index)
初始化index
的級別,使其具有與“ A”和“ B”相同的dtype。 希望這不是問題。
這將讓我們建立使用更簡單的解決loc
和基於索引的選擇和分配。
u = df.set_index(['A', 'B'])
u.loc[ser.index[ser], 'C'] = np.nan
u.reset_index()
A B C D
0 188 1 2.0 foo
1 750 2 5.0 foo
2 1330 4 7.0 foo
3 1385 5 NaN foo
4 188 1 5.0 bar
5 750 2 5.0 bar
6 810 3 NaN bar
7 1330 4 7.0 bar
8 1385 5 NaN bar
如果遇到給定ser
且需要更改索引pd.Index.set_levels
則可以使用pd.Index.set_levels
的列表理解來快速重建它。
ser.index = ser.index.set_levels([l.astype(int) for l in ser.index.levels])
# Alternative,
# ser.index = ser.index.set_levels([
# pd.to_numeric(l) for l in ser.index.levels])
現在,這有效:
u = df.set_index(['A', 'B'])
u.loc[ser.index[ser], 'C'] = np.nan
u.reset_index()
A B C D
0 188 1 2.0 foo
1 750 2 5.0 foo
2 1330 4 7.0 foo
3 1385 5 NaN foo
4 188 1 5.0 bar
5 750 2 5.0 bar
6 810 3 NaN bar
7 1330 4 7.0 bar
8 1385 5 NaN bar
注意loc
的ser.index[ser]
索引步驟,我們使用ser
的索引而不是直接使用index
。
采用:
# Converting ser to a dataframe
ndf = pd.DataFrame(ser).reset_index()
# Fetching B values against which C values needs to be mapped to NaN
idx = ndf[ndf.iloc[:,2] == True].B.values
# Fetching df index where C values needs to be mapped to NaN
idx_ = df[df.B.isin(idx)].index
# Mapping of C values to NaN
df.loc[idx_,'C'] = np.NaN
+---+------+---+-----+-----+
| | A | B | C | D |
+---+------+---+-----+-----+
| 0 | 188 | 1 | 2.0 | foo |
| 1 | 750 | 2 | 5.0 | foo |
| 2 | 1330 | 4 | 7.0 | foo |
| 3 | 1385 | 5 | NaN | foo |
| 4 | 188 | 1 | 5.0 | bar |
| 5 | 750 | 2 | 5.0 | bar |
| 6 | 810 | 3 | NaN | bar |
| 7 | 1330 | 4 | 7.0 | bar |
| 8 | 1385 | 5 | NaN | bar |
+---+------+---+-----+-----+
將isin
用於兩個MultiIndex
之間的檢查成員資格:
#convert columns to strings for same types of levels
df[['A','B']] = df[['A','B']].astype(str)
df.loc[df.set_index(['A','B']).index.isin(ser.index[ser]), 'C'] = np.nan
print (df)
A B C D
0 188 1 2.0 foo
1 750 2 5.0 foo
2 1330 4 7.0 foo
3 1385 5 NaN foo
4 188 1 5.0 bar
5 750 2 5.0 bar
6 810 3 NaN bar
7 1330 4 7.0 bar
8 1385 5 NaN bar
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.