Лучший способ присоединиться / объединиться в пандах

Я часто использую pandas для merge (join), используя условие диапазона.

Например, если имеется 2 кадра данных:

A (A_id, A_value)

B (B_id, B_low, B_high, B_name)

которые являются большими и примерно одинакового размера (скажем, 2M записей каждый).

Я хотел бы сделать внутреннее соединение между A и B, поэтому A_value будет находиться между B_low и B_high.

Используя синтаксис SQL, который будет:

SELECT * FROM A,B WHERE A_value between B_low and B_high 

и это было бы очень просто, коротко и эффективно.

Между тем в пандах единственный способ (который не использует петли, которые я нашел) – это создать фиктивный столбец в обеих таблицах, присоединиться к нему (эквивалентно перекрестному объединению), а затем отфильтровать ненужные строки. Это звучит тяжело и сложно:

 A['dummy'] = 1 B['dummy'] = 1 Temp = pd.merge(A,B,on='dummy') Result = Temp[Temp.A_value.between(Temp.B_low,Temp.B_high)] 

Еще одно решение, которое я использовал, – это применить к каждому из значений A функцию поиска на B с помощью B[(x>=B.B_low) & (x<=B.B_high)] , но она также неэффективна и может требуют оптимизации индекса.

Есть ли более элегантный и / или эффективный способ выполнения этого действия?

5 Solutions collect form web for “Лучший способ присоединиться / объединиться в пандах”

Настроить
Рассмотрим кадры данных A и B

 A = pd.DataFrame(dict( A_id=range(10), A_value=range(5, 105, 10) )) B = pd.DataFrame(dict( B_id=range(5), B_low=[0, 30, 30, 46, 84], B_high=[10, 40, 50, 54, 84] )) A A_id A_value 0 0 5 1 1 15 2 2 25 3 3 35 4 4 45 5 5 55 6 6 65 7 7 75 8 8 85 9 9 95 B B_high B_id B_low 0 10 0 0 1 40 1 30 2 50 2 30 3 54 3 46 4 84 4 84 

numpy
Самый простой способ – использовать numpy вещание.
Мы ищем каждый экземпляр A_value который больше или равен B_low , в то время как A_value меньше или равно B_high .

 a = A.A_value.values bh = B.B_high.values bl = B.B_low.values i, j = np.where((a[:, None] >= bl) & (a[:, None] <= bh)) pd.DataFrame( np.column_stack([A.values[i], B.values[j]]), columns=A.columns.append(B.columns) ) A_id A_value B_high B_id B_low 0 0 5 10 0 0 1 3 35 40 1 30 2 3 35 50 2 30 3 4 45 50 2 30 

Я не знаю, насколько он эффективен, но кто-то написал обертку, которая позволяет использовать синтаксис SQL с объектами pandas. Это называется пандаск . В документации явно указано, что соединения поддерживаются. Это может быть, по крайней мере, легче читать, поскольку синтаксис SQL очень читабельен.

Не уверен, что это более эффективно, однако вы можете напрямую использовать sql (например, из модуля sqlite3) с помощью pandas (вдохновленный этим вопросом ), например:

 conn = sqlite3.connect(":memory") df2 = pd.DataFrame(np.random.randn(10, 5), columns=["col1", "col2", "col3", "col4", "col5"]) df1 = pd.DataFrame(np.random.randn(10, 5), columns=["col1", "col2", "col3", "col4", "col5"]) df1.to_sql("df1", conn, index=False) df2.to_sql("df2", conn, index=False) qry = "SELECT * FROM df1, df2 WHERE df1.col1 > 0 and df1.col1<0.5" tt = pd.read_sql_query(qry,conn) 

Вы можете адаптировать запрос по мере необходимости в своем приложении

давайте рассмотрим простой пример:

 df=pd.DataFrame([2,3,4,5,6],columns=['A']) 

возвращается

  A 0 2 1 3 2 4 3 5 4 6 

теперь позволяет определить второй блок данных

 df2=pd.DataFrame([1,6,2,3,5],columns=['B_low']) df2['B_high']=[2,8,4,6,6] 

приводит к

  B_low B_high 0 1 2 1 6 8 2 2 4 3 3 6 4 5 6 

вот так; и мы хотим, чтобы результат был индексом 3 и значением 5

 df.where(df['A']>=df2['B_low']).where(df['A']<df2['B_high']).dropna() 

приводит к

  A 3 5.0 

Учтите, что ваш информационный кадр A

 A = pd.DataFrame([[0,2],[1,3],[2,4],[3,5],[4,6]],columns=['A_id', 'A_value']) 

и B –

 B = pd.DataFrame([[0,1,2,'a'],[1,4,9,'b'],[2,2,5,'c'],[3,6,7,'d'],[4,8,9,'e']],columns=['B_id', 'B_low', 'B_high', 'B_name']) 

используя это ниже, вы получите желаемый результат

 A = A[(A['A_value']>=B['B_low'])&(A['A_value']<=B['B_high'])] 
  • Панды: № установки. максимальных строк
  • Pandas: совокупная сумма одного столбца в зависимости от значения другого
  • Преобразовать данные о кадрах pandas из списков в dict dataframes
  • Укажите правильные типы данных, используя pandas.read_csv
  • Как удалить строку с определенной строкой с нулевым значением
  • утечка памяти при создании буфера с пандами?
  • Python-pandas Замените NA медианной или средней частью группы в области данных
  • Сохранить сеанс в IPython, как в MATLAB?
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.