Как присоединиться к кадру данных pandas в 2 столбцах?

Предположим, что следующие кадры данных

дф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

Вам нужно уточнить, как data12 генерируется из ваших фреймов данных.

petezurich 30.06.2019 10:31

@Gulzar data12 является результатом объединения идентификатора первого фрейма данных и id2 второго фрейма данных, верно?

cody 30.06.2019 10:36

@cody, если бы я знал, как правильно выполнять соединения в пандах, вы бы не увидели этот вопрос. см. edit2, пожалуйста, я думаю, что это отвечает на ваш вопрос

Gulzar 30.06.2019 10:43

Ok. Понятно. Смотрите мою правку.

petezurich 30.06.2019 10:47

Привет @Gulzar. Я понял ваш вопрос и отредактировал свой ответ в соответствии с требованием. Может быть, это поможет

cody 30.06.2019 10:50
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
5
189
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

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)

Я надеюсь, что это решит вашу проблему

Спасибо! что касается вычитания, я отредактирую, чтобы было ясно, что данные идеально вписываются в очевидный расчет. Теоретически это могут быть любые данные. хотел пояснить на примере

Gulzar 30.06.2019 10:23

Но это не отвечает на мой вопрос, пожалуйста, смотрите редактирование. расчет в вашей строке 4 не будет работать для произвольных данных

Gulzar 30.06.2019 10:25

@Gulzar, вы хотите вычесть данные2 и данные11?

tawab_shakeel 30.06.2019 10:26

@Gulzar, пожалуйста, объясните, что такое data12? data11 - это столбец, исходящий из df1, а data12 кажется вычитанием, поэтому я применил вычитание

tawab_shakeel 30.06.2019 10:29

Попробуй это:

# 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); просто для того, чтобы вы поняли различные подходы к слиянию в определенных столбцах, вот общее руководство.

Присоединение к кадрам данных в Pandas

Типы соединений 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

Другие вопросы по теме