Консолидация фреймов данных

#python #pandas #indexing

#python #панды #индексирование

Вопрос:

У меня есть 3 фрейма данных pandas с соответствующими индексами. Некоторые операции обрезают фреймы данных по-разному (удаляют строки), так что некоторые индексы в одном фрейме данных могут не существовать в другом.

Я хотел бы объединить все 3 фрейма данных, чтобы все они содержали строки с индексами, которые присутствуют во всех 3 из них. Как это достижимо?

 import pandas as pd
data = pd.DataFrame.from_dict({'a': [1,2,3,4], 'b': [3,4,5,6], 'c': [6,7,8,9]})

a = pd.DataFrame(data['a'])
b = pd.DataFrame(data['b'])
c = pd.DataFrame(data['c'])

a = a[a['a'] <= 3]
b = b[b['b'] >= 4]

# some operation here that removes rows that aren't present in all (intersection of all dataframe's indices)

print a
   a
1  2
2  3

print b
   b
1  4
2  5

print c
   c
1  7
2  8
  

Обновить

Извините, я увлекся и забыл, чего я хотел достичь, когда писал примеры. Фактическое намерение состояло в том, чтобы разделить 3 фрейма данных. Прошу прощения за вводящий в заблуждение пример (я исправил его сейчас).

Ответ №1:

Используйте merge и передавайте параметры left_index=True и right_index=True , тип слияния по умолчанию — внутренний, поэтому будут объединены только значения, которые существуют как слева, так и справа.

 In [6]:

a.merge(b, left_index=True, right_index=True).merge(c, left_index=True, right_index=True)
Out[6]:
   a  b  c
1  2  4  7
2  3  5  8

[2 rows x 3 columns]
  

Чтобы изменить исходные фреймы данных, чтобы они теперь содержали только строки, которые существуют во всех, вы можете сделать это:

 In [12]:

merged = a.merge(b, left_index=True, right_index=True).merge(c, left_index=True, right_index=True)
merged
Out[12]:
   a  b  c
1  2  4  7
2  3  5  8
In [14]:

a = a.loc[merged.index]
b = b.loc[merged.index]
c = c.loc[merged.index]
In [15]:

print(a)
print(b)
print(c)
   a
1  2
2  3
   b
1  4
2  5
   c
1  7
2  8
  

Итак, мы объединяем их все по значениям индекса, которые присутствуют во всех из них, а затем используем индекс для фильтрации исходных фреймов данных.

Комментарии:

1. Слияние кажется интересной альтернативой concat. Когда вы используете тот или иной? Это кажется merge более универсальным. Я обновил свой пост. То, как я это оформил, было не тем, что я на самом деле искал…

2. @orange исходные фреймы данных здесь не затрагиваются, если вы не передаете параметр inplace=True , поэтому возвращается копия

3. Извините, если это все еще не ясно. Я бы действительно хотел изменить исходные фреймы данных (или иметь их копии). Они должны содержать только те строки, индексы которых присутствуют во всех 3 фреймах данных.

Ответ №2:

Взгляните на concat, который можно использовать для различных комбинированных операций. Здесь вы хотите, чтобы join для типа было установлено значение inner (потому что требуется пересечение) и axis установлено значение 1 (объединение столбцов).

 In [123]: pd.concat([a,b,c], join='inner', axis=1)
Out[123]: 
   a  b  c
1  2  4  7
2  3  5  8
  

Комментарии:

1.Интересно merge , что для больших фреймов данных быстрее, чем concat, я сравнил concat с merge для фрейма данных 40000 строк и увидел это 100 loops, best of 3: 6.3 ms per loop 100 loops, best of 3: 4.87 ms per loop при сравнении concat с merge

2. Также еще быстрее, используя фрейм данных с 4 миллионами строк: 1 loops, best of 3: 694 ms per loop 1 loops, best of 3: 494 ms per loop , это было сделано с использованием pandas 0.14.0

3. Concat отлично работает. Есть ли какой-либо способ сохранить 3 фрейма данных отдельно? Извините, я перепутал пример.