Я пытаюсь сопоставить комбинацию значений в одном фрейме данных с той же комбинацией в другом (по сути, таблица поиска). Если я нахожу совпадение в таблице поиска, замените значения в оригинале из поиска. Я пробовал использовать replace, map, используя lo c, но мне кажется, что я больше запутываю себя.
У меня есть пример фрейма данных
example1 = {
'Code': ['99233','99233','99233','90732','93306','93306','93306'],
'Modifier': ['','','','','','TC','26'],
'W': ['0','0','0','0','0','0','0'],
'P': ['0','0','0','0','0','0','0'],
'M': ['0','0','0','0','0','0','0']
}
df1 = pd.DataFrame(example1)
который выглядит так,
Code Modifier W P M
0 99233 0 0 0
1 99233 0 0 0
2 99233 0 0 0
3 90732 0 0 0
4 93306 0 0 0
5 93306 TC 0 0 0
6 93306 26 0 0 0
Затем я бы использовал таблицу поиска, подобную следующей ...
example2 = {
'Code': ['99233','90732','93306','93306','93306'],
'Modifier': ['','','','TC','26'],
'W': ['2','0','1.5','0','1.5'],
'P': ['0.81','0','4.29','3.76','0.53'],
'M': ['0.13','0','0.7','0.2','0.05']
}
df2 = pd.DataFrame(example2)
Что выглядит так:
Code Modifier W P M
0 99233 2 0.81 0.13
1 90732 0 0 0
2 93306 1.5 4.29 0.7
3 93306 TC 0 3.76 0.2
4 93306 26 1.5 0.53 0.05
Я хочу иметь возможность используйте поля «Код» и «Модификатор» и замените значения W, P и M в основном фрейме данных (df1).
Мне удалось сопоставить одно значение, преобразовав таблицу поиска в series (я не уверен, что это правильно, но это имеет смысл) и использование кода в словаре в качестве индекса
vdic = pd.Series(df2.W.values, index=df2.Code).to_dict()
df1.loc[df1.Code.isin(vdic.keys()), 'W'] = df1.loc[(df1.Code.isin(vdic.keys())), 'Code'].map(vdic)
df1
Это приводит меня к середине пути с первым столбцом, но, очевидно, не выбирая вверх по модификатору.
Code Modifier W P M
0 99233 2 0 0
1 99233 2 0 0
2 99233 2 0 0
3 90732 0 0 0
4 93306 1.5 0 0
5 93306 TC 1.5 0 0
6 93306 26 1.5 0 0
Я попытался добавить второй индекс в словарь,
vdic = pd.Series(df2.W.values, index=[df2.Code, df2.Modifier]).to_dict()
{('99233', ''): '2',
('90732', ''): '0',
('93306', ''): '1.5',
('93306', 'TC'): '0',
('93306', '26'): '1.5'}
Я думаю, это сработает, но я должен сделать это сложнее, чем на самом деле есть, и все попытки пока не работают. Я проверил другие потоки, и код повсюду.
Любая помощь или предложения были бы очень признательны.
Также любопытно, могу ли я обновить все три столбца (W, P и M ) за один проход или это должно быть разделено?
Редактировать из первого ответа @ user13802115 (что было круто, кстати)
Я должен изменить вопрос и спросить, можно выполнить ту же операцию, когда фреймы данных имеют разный размер.
example3 = {
'Other1': ['1','7','4','54','9','43','22'],
'Other2': ['A','Z','Y','BB','7W','9','Left'],
'Code': ['99233','99233','99233','90732','93306','93306','93306'],
'Modifier': ['','','','','','TC','26'],
'W': ['0','0','0','0','0','0','0'],
'P': ['0','0','0','0','0','0','0'],
'M': ['0','0','0','0','0','0','0']
}
df3 = pd.DataFrame(example3)
По сути редактировать на месте и обновлять только значения из таблицы поиска в первом фрейме данных, оставляя другие, однако многие элементы, нетронутыми .
Решение ниже
Благодаря ответу @ user13802115 я использовал следующую ссылку: Pandas слияние фреймов данных разного размера на основе одного столбца
, чтобы получить то, что мне нужно. Используя измененный фрейм данных (df3), я могу выполнить следующее, чтобы объединить мои данные, отбросить добавленные значения в мой исходный фрейм данных и переиндексировать, чтобы все осталось в том виде, в каком оно было создано изначально, с обновленными полями.
df = (df3.merge(df2, on=['Code','Modifier'], how='left', suffixes=('_',''))
.drop(['W_','P_','M_'], axis=1)
.reindex(columns=df1.columns))
df