содержится ли строки одного датафрейма в другом датафрейме
Есть два датафрейма с одним стобцом данных (номера):
DF1
| Номер |
|---|
| 218456 |
| 789562 |
| 514 |
| 787862 |
| 894514 |
DF2
| Номер |
|---|
| 893514 |
| 787862 |
| 896514 |
| 789562 |
| 2184 |
Результат: добавить к df2 номера из df1, которые полностью совпадают или частично совпадают (совпадение строго слева)
| num | traf |
|---|---|
| 893514 | 0 |
| 787862 | 787862 |
| 896514 | 0 |
| 789562 | 789562 |
| 2184 | 218456 |
Мой вариант:
df2['traf'] =df2['num'].apply(lambda x: df1['num'][df1['num'].astype(str).str.contains(str(x))].values[0] if len(df1['num'][df1['num'].astype(str).str.contains(str(x))].values) > 0 else 0)
Работает медленно и также добавляет номера, которые могут содержаться не слева, а по середине в том числе.
Ответы (1 шт):
Автор решения: strawdog
→ Ссылка
В общем, если я правильно понял вопрос, то сделать можно так (я добавил повторяющееся значение в df1 для чистоты эксперимента), однако затратность все равно высокая:
Исходные:
import pandas as pd
df1 = pd.DataFrame({"num":[218456,789562,514,787862,894514,218456]})
df2 = pd.DataFrame({"num":[893514,787862,896514,789562,2184]})
решение:
tmp = df1.merge(df2, how="cross").drop_duplicates()
tmp = tmp[tmp.apply(lambda x: str(x["num_x"]).startswith(str(x["num_y"])), axis=1)]
tmp = df2.merge(tmp, left_on="num", right_on="num_y", how="left")#.drop(columns=["num_x"])
tmp["traf"] = tmp.groupby("num")["num_y"].transform("count")
tmp = tmp.drop(columns=["num_x", "num_y"]).drop_duplicates()
tmp:
num traf
0 893514 0
1 787862 1
2 896514 0
3 789562 1
4 2184 2
Можно еще после merge сразу сделать новый датафрейм, к примеру, с указанием списка совпадений, а не их количества:
res = tmp.groupby("num")["num_x"].apply(lambda x: list(x) if not x.isna().all() else None).reset_index().rename(columns={"num_x":"traf"})
res:
num traf
0 2184 [218456.0, 21845.0]
1 787862 [787862.0]
2 789562 [789562.0]
3 893514 None
4 896514 None