2017-02-02 11 views
2

У меня есть 2 кадра данных Pandas, которые имеют неравную длину. Я привел пример ниже. Мой код должен пропустить значение яблок в 1-м кадре данных и найти его, если он существует во втором (всегда будет значение, существующее во втором фрейме данных). Если он находит одно и то же значение, тогда он должен хранить разницу апельсинов в 2 кадрах данных в 1-й кадр данных. Я выполнил эту задачу, используя 2 для циклов, которые также приведены ниже. Следующий код выполняет эту задачу, но мои фактические данные имеют 2 миллиона записей, а второй кадр данных содержит 800 записей. Использовать 2 для циклов сильно замедляет мою программу. Есть ли более эффективный способ выполнения этой задачи?Идентификация аналогичных значений путем итерации между двумя кадром данных Pandas.

trial={'apples': [2,4,1,5,3,2,1,1,4,5],'oranges': [8,5,9,4,2,6,7,5,1,3]} 
trial1={'apples': [1,2,3,4,5],'oranges': [2,5,6,3,1]} 
df=pd.DataFrame.from_dict(trial) 
df1=pd.DataFrame.from_dict(trial1) 
F=[] 
for i in df.apples.index: 
    for j in df1.apples.index: 
     if df.apples.ix[i]== df1.apples.ix[j]: 
      F.append(df.oranges.ix[i]-df1.oranges.ix[j])     
df['difference']=F 

ответ

2

Вы можете выполнить левый тип merge на колонке яблок, то вы можете позвонить diff на враждующих колоннах orange_x и orange_y, а затем инвертировать знак с помощью - и бросания в int с помощью astype:

In [159]: 
df['difference'] = -df.merge(df1, on='apples', how='left').ix[:, 'oranges_x':].diff(axis=1)['oranges_y'].astype(int) 
df 

Out[159]: 
    apples oranges difference 
0  2  8   3 
1  4  5   2 
2  1  9   7 
3  5  4   3 
4  3  2   -4 
5  2  6   1 
6  1  7   5 
7  1  5   3 
8  4  1   -2 
9  5  3   2 

разрывая выше вниз:

In [162]: 
df.merge(df1, on='apples', how='left') 

Out[162]: 
    apples oranges_x oranges_y 
0  2   8   5 
1  4   5   3 
2  1   9   2 
3  5   4   1 
4  3   2   6 
5  2   6   5 
6  1   7   2 
7  1   5   2 
8  4   1   3 
9  5   3   1 

In [163]: 
df.merge(df1, on='apples', how='left').ix[:, 'oranges_x':].diff(axis=1) 

Out[163]: 
    oranges_x oranges_y 
0  NaN  -3.0 
1  NaN  -2.0 
2  NaN  -7.0 
3  NaN  -3.0 
4  NaN  4.0 
5  NaN  -1.0 
6  NaN  -5.0 
7  NaN  -3.0 
8  NaN  2.0 
9  NaN  -2.0 

In [164]: 
-df.merge(df1, on='apples', how='left').ix[:, 'oranges_x':].diff(axis=1)['oranges_y'].astype(int) 

Out[164]: 
0 3 
1 2 
2 7 
3 3 
4 -4 
5 1 
6 5 
7 3 
8 -2 
9 2 
Name: oranges_y, dtype: int32 

Если реальные данные имеют больше столбцов, вы можете сделать это в отдельных шагах, если порядок следования столбцов отличаются от вашего примера:

In [170]: 
merged = df.merge(df1, on='apples', how='left') 
merged['difference'] = merged['oranges_x'] - merged['oranges_y'] 
merged 

Out[170]: 
    apples oranges_x oranges_y difference 
0  2   8   5   3 
1  4   5   3   2 
2  1   9   2   7 
3  5   4   1   3 
4  3   2   6   -4 
5  2   6   5   1 
6  1   7   2   5 
7  1   5   2   3 
8  4   1   3   -2 
9  5   3   1   2 

Таким образом, после слияния, падения лишних столбцов и переименовать обратно:

In [171]:  
merged = merged.drop('oranges_y', axis=1).rename(columns={'oranges_x':'oranges'}) 
merged 

Out[171]: 
    apples oranges difference 
0  2  8   3 
1  4  5   2 
2  1  9   7 
3  5  4   3 
4  3  2   -4 
5  2  6   1 
6  1  7   5 
7  1  5   3 
8  4  1   -2 
9  5  3   2 
+0

Большое спасибо. Это именно то, что я искал. –

+0

Вы можете принять мой ответ, если он разрешит ваш вопрос, в левом верхнем углу моего ответа будет пустой знак галочки, так что вопрос не останется без ответа. – EdChum

+0

Привет, Это действительно работает. Но для моих данных разница для всех столбцов - нан. Однако я могу видеть, что в двух кадрах данных есть соответствующие значения. Метод 2 для цикла работает и дает результаты. –