我正在尝试将数据帧列的值替换为同一列但来自另一行的值。
类型为“TO_REPLACE”的国家/地区的 ID 必须替换为类型为“ORIGINAL”的同一国家/地区的 ID。
DF 示例:
ID NAME TYPE
---
ID1 COUNTRY1 ORIGINAL <-- ORIGINAL of COUNTRY1 (ID1)
ID2 COUNTRY1 TO_REPLACE1 <-- ID must be ID1
ID3 COUNTRY1 TO_REPLACE2 <-- ID must be ID1
...
ID4 COUNTRYX TO_REPLACE1 <-- ID must be ID6
ID5 COUNTRYX TO_REPLACE2 <-- ID must be ID6
ID6 COUNTRYX ORIGINAL <-- ORIGINAL of COUNTRYX (ID6)
我需要: 如果-TYPE-是“TO_REPLACE1”或“TO_REPLACE2”,则找到-NAME-和-TYPE-“ORIGINAL”并将“ORIGINAL ID”放在ID上。 在此示例的末尾,所有 -NAME- COUNTRY1 必须为 ID1(“原始”ID),而 COUNTRYX 必须为 ID6。
结果:
ID NAME TYPE
---
ID1 COUNTRY1 ORIGINAL
ID1 COUNTRY1 TO_REPLACE1 <-- ID replaced
ID1 COUNTRY1 TO_REPLACE2 <-- ID replaced
...
ID6 COUNTRYX TO_REPLACE1 <-- ID replaced
ID6 COUNTRYX TO_REPLACE2 <-- ID replaced
ID6 COUNTRYX ORIGINAL
经过多次尝试,最接近的是这个:
df.loc[(df['TYPE'].isin(['TO_REPLACE1', 'TO_REPLACE2']), 'ID'] = df.loc[df['TYPE'] == 'ORIGINAL', 'ID'].values[0]
但仅替换为找到的第一个“原始 ID”。
mask
/where
并使用 groupby.transform
:
df['ID'] = (df['ID']
.where(df['TYPE'].eq('ORIGINAL'))
.groupby(df['NAME']).transform('first')
)
map
:
df['ID'] = df['NAME'].map(df[df['TYPE'].eq('ORIGINAL')].set_index('NAME')['ID'])
如果您确实需要匹配“ORIGINAL”和“TO_REPLACE”(假设其他值),则可以使用更通用的方法:
df['ID'] = (df['ID']
.mask(df['TYPE'].str.startswith('TO_REPLACE'))
.fillna(df['NAME'].map(df[df['TYPE'].eq('ORIGINAL')]
.set_index('NAME')['ID']))
)
输出:
ID NAME TYPE
0 ID1 COUNTRY1 ORIGINAL
1 ID1 COUNTRY1 TO_REPLACE1
2 ID1 COUNTRY1 TO_REPLACE2
3 ID6 COUNTRYX TO_REPLACE1
4 ID6 COUNTRYX TO_REPLACE2
5 ID6 COUNTRYX ORIGINAL