Заменить значения в одном датафрейме на значения из другого по услови
Есть два датафрейма, необходимо заменить значения в первом датафрейме на айдишники из второго датафрейма, если значениясовпадают по колонкам
df1 = pd.DataFrame(
{
"col1": ["string1", "string2"],
"col2": [np.NaN, "string1"],
"col3": ["string2", np.NaN ],
"col1_name": [np.NaN, np.NaN],
"col2_name": ["first_name", np.NaN],
"col3_name": [np.NaN, "last_name"]
}
)
df2 = pd.DataFrame(
{
"string": ["string1", "string2"],
"name": ["first_name", "last_name"],
"desc": ["description 102", "description 103"],
"id_": [101, 202]
}
)
Пробовал сделать так (к каждой колонке):
df1.col1 = df1.col1.apply(lambda x: df2[df2["string"] == x].id_)
Но работает не так, как я этого ожидаю (не очень понимаю печему оно так...)
Хотелось бы увидеть в этом (df1.col1) случае:
col1 |
101 |
202 |
Поясните , пожалуйста, почему ответ другой и как можно поправить?
PS: я понимаю что при вызове df1.col1.apply(lambda x: df2[df2["string"] == x].id_) возвращается датафрейм 2х2, но не понимаю почему.
Ответы (2 шт):
Решил эту задачу путем создания мапперов
string_mapper = dict(zip(df2.string, df2.id_))
name_mapper = dict(zip(df2.name, df2.id_))
df1.col1 = df1.col1.map(string_mapper)
df1.col1_name = df1.col1_name.map(name_mapper)
Если я правильно понял вопрос, а я в этом сомневаюсь, то можно еще такое сделать:
res = df1.applymap(lambda x: df2.loc[df2.eq(x).any(1), "id_"]
.values).applymap(lambda x:x.flat[0] if x.size>0 else np.nan)
тогда при ваших исходных, res будет:
col1 col2 col3 col1_name col2_name col3_name
0 101 NaN 202.0 NaN 101.0 NaN
1 202 101.0 NaN NaN NaN 202.0
разумеется, тип float появился из-за np.nan. Вы можете заменить это по своему усмотрению.