#python #pandas #dataframe #merge
#питон #панды #фрейм данных #слияние
Вопрос:
У меня есть образец фрейма данных
df = pd.DataFrame({'foo': [1, 2, 3], 'bar': ['A', 'B', 'C']})
и серия
pd.Series([3, 4, 5, 6], name='buzz')
Я хочу объединить их, чтобы каждая строка серии реплицировалась для каждой df
строки
, так что результирующий фрейм данных эквивалентен этому
pd.DataFrame({
'foo': [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
'bar': ['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C'],
'buzz': [3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6]
})
Я не могу использовать df.merge
с внешним соединением, потому что эти два столбца не имеют общих столбцов.
Это довольно легко сделать с помощью обычного python, но мне было интересно, есть ли лучшее решение pandas.
Ответ №1:
Вы можете добавить общий столбец для обоих для перекрестного соединения с Series.to_frame
для преобразования Series
в один столбец DataFrame
:
df = s.to_frame().assign(a=1).merge(df.assign(a=1), on='a').drop('a', axis=1)
print (df)
buzz foo bar
0 3 1 A
1 3 2 B
2 3 3 C
3 4 1 A
4 4 2 B
5 4 3 C
6 5 1 A
7 5 2 B
8 5 3 C
9 6 1 A
10 6 2 B
11 6 3 C
Или:
df = df.assign(a=1).merge(s.to_frame().assign(a=1), on='a').drop('a', axis=1)
print (df)
foo bar buzz
0 1 A 3
1 1 A 4
2 1 A 5
3 1 A 6
4 2 B 3
5 2 B 4
6 2 B 5
7 2 B 6
8 3 C 3
9 3 C 4
10 3 C 5
11 3 C 6
Другая идея заключается в использовании numpy.tile
и numpy.repeat
:
df = (df.loc[np.tile(df.index, len(s))]
.reset_index(drop=True)
.assign(buzz = np.repeat(s.to_numpy(), len(df))))
print (df)
foo bar buzz
0 1 A 3
1 2 B 3
2 3 C 3
3 1 A 4
4 2 B 4
5 3 C 4
6 1 A 5
7 2 B 5
8 3 C 5
9 1 A 6
10 2 B 6
11 3 C 6
РЕДАКТИРОВАТЬ: если все столбцы имеют одинаковые типы (не такие, как здесь), возможно ли использовать решение @Ch3ster, спасибо:
Используя np.tile
и np.repeat
df_arr = np.tile(df.to_numpy(), (len(s), 1))
s_arr = np.repeat(s.to_numpy(), len(df))
df = pd.DataFrame(
np.column_stack([df_arr, s_arr]), columns=[*df.columns, s.name]
)
Комментарии:
1. @Ch3steR — Проблема вашего решения в том, что все значения являются строками: (
2. Никаких проблем с отменой изменений 😉 Хороший ответ
3. @Ch3steR — он был повторно использован для использования
np.tile
с индексом иloc
4. @Ch3steR — Спасибо, также открыт заново, потому что частично обманывает.
5. @Ch3steR — Я думаю, лучше включить ваше решение в ответ, спасибо.