Вопрос по объединению DataFrame
Есть dataframe
| ID | Name | Price |
|---|---|---|
| Совпадение | Название1 | Цена1 |
| 21cd1231dw | czxca21 | 1324512 |
| Совпадение | Название2 | Цена2 |
| Совпадение | Название3 | Цена3 |
Надо по нему пробежаться и если совпадает id добавляем дубль справа в столбцы с названием name_1 и price_1
если совпадений несколько то добавляем name_2 , name_55 и тд
пробовал поиграться с объединением dataframe merge:
df_merged = df.merge(df, on='ID')
Дубли не удаляет на выходе получается
| ID | Name | Price | NAme_x | Price_x" |
|---|---|---|---|---|
| Совпадение | Название1 | цена 1 | Название2 | Цена2 |
| Совпадение | Название1 | цена 1 | Название 3 | Цена3 |
| 3123asdas | asdased2 | 12315125 |
Если использую
df_merged = df.join(df, rsuffix='_right')
просто находит строку и справа делает ее дубль
Короче все варианты перепробовал и более или мене что работает это .merge и то дубли оставляет.
Объясните пожалуйста, что делаю не так?
Получается даже не так, просто он находит строку и копирует ее справа за исключением ID. А нужно чтобы все id объединились в одну строку.
На выходе я хочу получить
| ID | Name | Price | NAme_x | Price_x" | Name_y | Price_y |
|---|---|---|---|---|---|---|
| Совпадение1 | Название1 | цена 1 | Название2 | Цена2 | Название3 | Цена3 |
| Совпадение2 | ыфввыф | 15251423 | фывфыв | 12331 | ||
| Совпадение3 | asdased2 | 12315125 |
т.е 1 строка формируется из всех строк с значением id = Совпадение1, а справа пишем значения Name и Price тех строк где id совпало и тд
Ответы (1 шт):
Можно так попробовать.
Допустим у нас есть такой df
>>> df
id name price
0 1 a 100
1 1 b 200
2 1 c 300
3 2 d 400
4 2 e 500
5 2 f 600
6 3 g 700
7 3 h 800
8 1 j 900
Тогда.
Вариант 1:
new_df = df.assign(k=df.groupby(['id']).cumcount()).set_index(['id', 'k']).unstack()
Переименуем столбцы
new_df.columns = [f'{x}_{y}' for x, y in new_df.columns]
Отсортируем, чтобы столбцы были в нужном вам порядке и сбросим индекс
new_df = new_df.reindex(sorted(new_df.columns, key=lambda x: x[-1]), axis=1).reset_index()
Получаем:
>>> new_df
id name_0 price_0 name_1 price_1 name_2 price_2 name_3 price_3
0 1 a 100.0 b 200.0 c 300.0 j 900.0
1 2 d 400.0 e 500.0 f 600.0 NaN NaN
2 3 g 700.0 h 800.0 NaN NaN NaN NaN
Вариант 2 (Вроде проще):
Без группировке в данном случае все равно никуда, поэтому
df = df.groupby('id').agg(name=('name', lambda x: x.to_list()), price=('price', lambda x: x.to_list())).reset_index()
Далее создадим функцию, которая принимает на вход ваш датафрейм и название столбца и возвращает новый датафрейм.
def return_col(your_df, col: str):
list_of = your_df[col].to_list()
max_len_of = max([len(i) for i in list_of])
df_of = pd.DataFrame(list_of, columns=[f'{col}_{i}' for i in range(max_len_of)]).fillna(np.nan)
return df_of
пример:
>>> print(return_col(df, 'name'))
name_0 name_1 name_2 name_3
0 a b c j
1 d e f NaN
2 g h NaN NaN
с помощью данной функции создадим несколько новых df для начальных столбцов
name = return_col(df, 'name')
price = return_col(df, 'price')
соединим их и отсортируем
df_np = pd.concat([name, price], axis=1)
df_np = df_np[sorted(df_np, key=lambda x: x[-1])]
и добавим наш id
df_last = pd.concat([df['id'], df_np], axis=1)
получим
>>> df_last
id name_0 price_0 name_1 price_1 name_2 price_2 name_3 price_3
0 1 a 100 b 200 c 300.0 j 900.0
1 2 d 400 e 500 f 600.0 NaN NaN
2 3 g 700 h 800 NaN NaN NaN NaN
p.s. На мой взгляд первый вариант надежнее