Я пытаюсь объединить столбцы динамически. Имена столбцов хранятся в виде строк с разделителями в столбце «слияние»:
import pandas as pd
df = pd.DataFrame({'prodName': ['p1', 'p2', 'p3'],
'mfr': ['m1', 'm2', 'm3'],
'segment': ['s1','s2','s3'],
'brand': ['b1','b2','b3'],
'merge': ['mfr!segment','mfr!brand','segment!brand']})
df
df
вывод:
prodName mfr segment brand merge
0 p1 m1 s1 b1 mfr!segment
1 p2 m2 s2 b2 mfr!brand
2 p3 m3 s3 b3 segment!brand
df
ожидаемый результат:
prodName mfr segment brand merge new_col
0 p1 m1 s1 b1 mfr!segment m1_s1
1 p2 m2 s2 b2 mfr!brand m2_b2
2 p3 m3 s3 b3 segment!brand s3_b3
Я пытался использовать pd.factorise
, но он ожидает данные 1D.
Я добился желаемого результата, перебирая строки
for index, row in df:
colstomerge=[col for col in row["merge"].lower().split("!")]
df['new_col']=df.loc[:,colstomerge].astype(str).sum(axis=1)
Я ищу более элегантное и оптимальное решение, спасибо.
Вы можете использовать apply()
и определить функцию, которая выполняет конкатенацию в зависимости от столбца merge
:
import pandas as pd
# Define function to merge strings depending on merge col
def merger(x):
a, b = x['merge'].split('!')
return x[a] + "_" + x[b]
df = pd.DataFrame({'prodName': ['p1', 'p2', 'p3'],
'mfr': ['m1', 'm2', 'm3'],
'segment': ['s1','s2','s3'],
'brand': ['b1','b2','b3'],
'merge': ['mfr!segment','mfr!brand','segment!brand']})
# Apply function to rows
df['new_col'] = df.apply(merger, axis=1)
df
вывод:
prodName mfr segment brand merge new_col
0 p1 m1 s1 b1 mfr!segment m1_s1
1 p2 m2 s2 b2 mfr!brand m2_b2
2 p3 m3 s3 b3 segment!brand s3_b3
Вы можете сделать следующее - назначить временный столбец со списком столбцов, которые нужно объединить, и объединить с помощью .join. Он должен работать для любого количества столбцов, разделенных '!' в столбце "объединить"
df["new_col"] = df.assign(cols=df["merge"].str.split("\!")).apply(
lambda row: "_".join(row[row["cols"]].fillna("")), axis=1
)
print(df)
df
вывод:
prodName mfr segment brand merge new_col
0 p1 m1 s1 b1 mfr!segment m1_s1
1 p2 m2 s2 b2 mfr!brand m2_b2
2 p3 m3 s3 b3 segment!brand s3_b3
Спасибо, у меня все еще есть проблемы с нанами, например, представьте, если «mfr» - это нан для одного из строк
Вы можете сделать fillna("")
в лямбде, как отредактировано в ответе, тогда np.nan будет отображаться как пустой, например. _b2 если m2 был np.nan, если вам нужна какая-то другая строка, такая как «nan», просто введите fillna («nan»)
спасибо за ваш ответ, мне действительно нужно объединить более 2 столбцов в моем реальном наборе данных