Предположим, что следующие кадры данных
дф1:
id data1
1 10
2 200
3 3000
4 40000
дф2:
id1 id2 data2
1 2 210
1 3 3010
1 4 40010
2 3 3200
2 4 40200
3 4 43000
Я хочу новый df3:
id1 id2 data2 data11 data12
1 2 210 10 200
1 3 3010 10 3000
1 4 40010 10 40000
2 3 3200 200 3000
2 4 40200 200 40000
3 4 43000 3000 40000
Каков правильный способ добиться этого в пандах?
Обновлено: пожалуйста, не конкретные данные могут быть произвольными. Я выбрал эти конкретные данные только для того, чтобы показать, откуда все берется, но каждый элемент данных не имеет корреляции с каким-либо другим элементом данных.
Другие примеры фреймов данных, потому что первый был недостаточно ясен:
ЛФ4:
id data1
1 a
2 b
3 c
4 d
df5:
id1 id2 data2
1 2 e
1 3 f
1 4 g
2 3 h
2 4 i
3 4 j
Я хочу новый df6:
id1 id2 data2 data11 data12
1 2 e a b
1 3 f a c
1 4 g a d
2 3 h b c
2 4 i b d
3 4 j c d
Редактировать2:
Data11 и Data12 — это просто копия data1 с соответствующим идентификатором id1 или id2
@Gulzar data12 является результатом объединения идентификатора первого фрейма данных и id2 второго фрейма данных, верно?
@cody, если бы я знал, как правильно выполнять соединения в пандах, вы бы не увидели этот вопрос. см. edit2, пожалуйста, я думаю, что это отвечает на ваш вопрос
Ok. Понятно. Смотрите мою правку.
Привет @Gulzar. Я понял ваш вопрос и отредактировал свой ответ в соответствии с требованием. Может быть, это поможет






1. Сначала объедините оба кадра данных, используя столбец id1 и id
2. переименовать data1 как data11
3. удалить столбец идентификатора
4. Теперь объединяем df1 и df3 по id2 и id
df3 = pd.merge(df2,df1,left_on=['id1'],right_on=['id'],how='left')
df3.rename(columns = {'data1':'data11'},inplace=True)
df3.drop('id',axis=1,inplace=True)
df3 = pd.merge(d3,df1,left_on=['id2'],right_on=['id'],how='left')
df3.rename(columns = {'data1':'data12'},inplace=True)
df3.drop('id',axis=1,inplace=True)
Я надеюсь, что это решит вашу проблему
Спасибо! что касается вычитания, я отредактирую, чтобы было ясно, что данные идеально вписываются в очевидный расчет. Теоретически это могут быть любые данные. хотел пояснить на примере
Но это не отвечает на мой вопрос, пожалуйста, смотрите редактирование. расчет в вашей строке 4 не будет работать для произвольных данных
@Gulzar, вы хотите вычесть данные2 и данные11?
@Gulzar, пожалуйста, объясните, что такое data12? data11 - это столбец, исходящий из df1, а data12 кажется вычитанием, поэтому я применил вычитание
Попробуй это:
# merge dataframes, first on id and id1 then on id2
df3 = pd.merge(df1, df2, left_on = "id", right_on = "id1", how = "inner")
df3 = pd.merge(df1, df3, left_on = "id", right_on = "id2", how = "inner")
# rename and reorder columns
cols = [ 'id1', 'id2', 'data2', 'data1_y', 'data1_x']
df3 = df3[cols]
new_cols = ["id1", "id2", "data2", "data11", "data12"]
df3.columns = new_cols
df3.sort_values("id1", inplace=True)
print(df3)
Это распечатывает:
id1 id2 data2 data11 data12
0 1 2 210 10 200
1 1 3 3010 10 3000
2 1 4 40010 10 40000
3 2 3 3200 200 3000
4 2 4 40200 200 40000
5 3 4 43000 3000 40000
Как упоминал ранее @tawab_shakeel, ваш основной шаг — объединить кадры данных в определенном столбце на основе определенных правил соединения (SQL); просто для того, чтобы вы поняли различные подходы к слиянию в определенных столбцах, вот общее руководство.

одно из решений вашей проблемы:
data1 = {'id' : [1,2,3,4],
'data1' : [10,200,3000,40000]}
data2 = {'id1' : [1,1,1,2,2,3],
'id2' : [2,3,4,3,4,4],
'data2' : [210,3010,40010,3200,40200,43000]}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
df1:
id data1
1 10
2 200
3 3000
4 40000
df2:
id1 id2 data2
1 2 210
1 3 3010
1 4 40010
2 3 3200
2 4 40200
3 4 43000
df3 = df2.set_index('id1').join(df1.set_index('id'))
df3.index.names = ['id1']
df3.reset_index(inplace=True)
final = df3.set_index('id2').join(df1.set_index('id'), rsuffix='2')
final.index.names = ['id2']
final.reset_index(inplace=True)
final[['id1','id2','data2','data1','data12']].sort_values('id1')
output df:
id1 id2 data2 data1 data12
1 2 210 10 200
1 3 3010 10 3000
1 4 40010 10 40000
2 3 3200 200 3000
2 4 40200 200 40000
3 4 43000 3000 40000
Я надеюсь, что это поможет вам.
merge в цикле for с range и f-stringОдин из способов, которым мы можем обобщить это и упростить расширение при наличии более двух фреймов данных, — это использовать list comprehension и цикл for с range.
После этого мы удаляем повторяющиеся имена столбцов:
dfs = [df2.merge(df1,
left_on=f'id{x+1}',
right_on='id',
how='left').rename(columns = {'data1':f'data1{x+1}'}) for x in range(2)]
df = pd.concat(dfs, axis=1).drop('id', axis=1)
df = df.loc[:, ~df.columns.duplicated()]
Выход
id1 id2 data2 data11 data12
0 1 2 210 10 200
1 1 3 3010 10 3000
2 1 4 40010 10 40000
3 2 3 3200 200 3000
4 2 4 40200 200 40000
5 3 4 43000 3000 40000
используйте два левых слияния в столбцах id1 и id2 для фрейма данных df2
txt="""идентификатор,данные1 1,а 2,б 3,в 4, г """
from io import StringIO
f = StringIO(txt)
df1 = pd.read_table(f,sep =',')
df1['id']=df1['id'].astype(int)
txt = """id1,id2,data2
1,2,e
1,3,f
1,4,g
2,3,h
2,4,i
3,4,j
"""
f = StringIO(txt)
df2 = pd.read_table(f,sep =',')
df2['id1']=df2['id1'].astype(int)
df2['id2']=df2['id2'].astype(int)
left_on='id1'
right_on='id'
suffix='_1'
df2=df2.merge(df1, how='left', left_on=left_on, right_on=right_on,
suffixes=("", suffix))
left_on='id2'
right_on='id'
suffix='_2'
df2=df2.merge(df1, how='left', left_on=left_on, right_on=right_on,
suffixes=("", suffix))
print(df2)
выход
id1 id2 data2 id data1 id_2 data1_2
0 1 2 e 1 a 2 b
1 1 3 f 1 a 3 c
2 1 4 g 1 a 4 d
3 2 3 h 2 b 3 c
4 2 4 i 2 b 4 d
5 3 4 j 3 c 4 d
Вам нужно уточнить, как
data12генерируется из ваших фреймов данных.