2016-04-03 4 views
4

У меня есть два кадра данных pandas. Первый:Python Pandas - Объединение двух фреймов данных на основе индекса порядка

df1 = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"]}) 

второй фрейм данные:

df2 = pd.DataFrame({"val1" : ["A1","A1","A1","B2","B2","B2"], 
        "val2" : [10, 13, 16, 11, 20, 22]}) 

Я хотел бы объединить два вместе таким образом, в котором используется упорядочение строк из df1 и значения из df2 следует это упорядочение. В идеале, я хотел бы, чтобы выглядеть следующим образом:

df_final = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"], 
         "val2" : [11, 10, 20, 13, 22, 16]}) 

Я попытался с помощью функции слияния с left_on и right_on, но я не получаю выход я ищу. Любая помощь будет принята с благодарностью.

+0

Может быть, 'df2.update (df1)', а затем сортировать vals? –

+0

@PadraicCunningham, вопрос в том, как их сортировать? ;) – MaxU

+0

@MaxU, это довольно легко сделать с обычным python –

ответ

1

Вы можете сделать это следующим образом:

  1. значения сортировки в df2 по ['val1', 'val2'], группа его по val1 и сохранить его как g2?
  2. добавить idx столбец df1, который будет использоваться для того, чтобы выбрать значения из df2

Код:

In [176]: df1['idx'] = 1 

In [177]: df1['idx'] = df1.groupby('val1')['idx'].cumsum()-1 

In [178]: df1 
Out[178]: 
    val1 idx 
0 B2 0 
1 A1 0 
2 B2 1 
3 A1 1 
4 B2 2 
5 A1 2 

In [179]: g2 = df2.sort_values(['val1', 'val2']).groupby('val1') 

In [180]: g2.groups 
Out[180]: {'A1': [0, 1, 2], 'B2': [3, 4, 5]} 

In [181]: df2.iloc[g2.groups['A1'][1]] 
Out[181]: 
val1 A1 
val2 13 
Name: 1, dtype: object 

In [182]: df1.apply(lambda x: df2.iloc[g2.groups[x['val1']][x['idx']]], axis=1) 
Out[182]: 
    val1 val2 
0 B2 11 
1 A1 10 
2 B2 20 
3 A1 13 
4 B2 22 
5 A1 16 
0

Вы можете использовать groupby/cumcount присвоить уникальный номер для каждой строки в каждой группе:

df1['cumcount'] = df1.groupby('val1').cumcount() 
# val1 cumcount 
# 0 B2   0 
# 1 A1   0 
# 2 B2   1 
# 3 A1   1 
# 4 B2   2 
# 5 A1   2 

Если мы делаем то же самое df2:

df2['cumcount'] = df2.groupby('val1').cumcount() 
# val1 val2 cumcount 
# 0 A1 10   0 
# 1 A1 13   1 
# 2 A1 16   2 
# 3 B2 11   0 
# 4 B2 20   1 
# 5 B2 22   2 

затем слияния df1 с df2 на общих столбцов (val1 и cumcount) дает желаемый результат:

import numpy as np 
import pandas as pd 

df1 = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"]}) 
df2 = pd.DataFrame({"val1" : ["A1","A1","A1","B2","B2","B2"], 
        "val2" : [10, 13, 16, 11, 20, 22]}) 
df_final = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"], 
         "val2" : [11, 10, 20, 13, 22, 16]}) 

df1['cumcount'] = df1.groupby('val1').cumcount() 
df2['cumcount'] = df2.groupby('val1').cumcount() 
result = pd.merge(df1, df2, how='left') 
result = result.drop('cumcount', axis=1) 
print(result) 
assert result.equals(df_final) 

урожаи

val1 val2 
0 B2 11 
1 A1 10 
2 B2 20 
3 A1 13 
4 B2 22 
5 A1 16 

Заметьте, что слияние с how='left' дает результат с такое же количество строк, что и первый DataFrame, df1 и поддерживает тот же порядок o f строк как df1.

Смежные вопросы