#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 с merge2. Также еще быстрее, используя фрейм данных с 4 миллионами строк:
1 loops, best of 3: 694 ms per loop 1 loops, best of 3: 494 ms per loop
, это было сделано с использованием pandas0.14.0
3. Concat отлично работает. Есть ли какой-либо способ сохранить 3 фрейма данных отдельно? Извините, я перепутал пример.