Как вычесть строки одного фрейма данных pandas из другого?

операция, которую я хочу сделать, похожа на слияние. Например, с помощью inner слияние мы получаем фрейм данных, содержащий строки, присутствующие в первом и втором фреймах данных. С outer слияние мы получаем фрейм данных, которые присутствуют либо в первом, либо во втором фрейме данных.

мне нужен фрейм данных, содержащий строки, которые присутствуют в первом фрейме данных и не присутствуют во втором? Есть быстрый и элегантный способ сделать это?

3 ответов


как насчет чего-то вроде следующего?

print df1

    Team  Year  foo
0   Hawks  2001    5
1   Hawks  2004    4
2    Nets  1987    3
3    Nets  1988    6
4    Nets  2001    8
5    Nets  2000   10
6    Heat  2004    6
7  Pacers  2003   12

print df2

    Team  Year  foo
0  Pacers  2003   12
1    Heat  2004    6
2    Nets  1988    6

пока есть неключевой обычно именованный столбец, вы можете позволить добавленным суффексам выполнять работу (если нет неключевого общего столбца, вы можете создать его для временного использования ... df1['common'] = 1 и df2['common'] = 1):

new = df1.merge(df2,on=['Team','Year'],how='left')
print new[new.foo_y.isnull()]

     Team  Year  foo_x  foo_y
0  Hawks  2001      5    NaN
1  Hawks  2004      4    NaN
2   Nets  1987      3    NaN
4   Nets  2001      8    NaN
5   Nets  2000     10    NaN

или вы можете использовать isin но вам придется создать один ключ:

df1['key'] = df1['Team'] + df1['Year'].astype(str)
df2['key'] = df1['Team'] + df2['Year'].astype(str)
print df1[~df1.key.isin(df2.key)]

     Team  Year  foo         key
0   Hawks  2001    5   Hawks2001
2    Nets  1987    3    Nets1987
4    Nets  2001    8    Nets2001
5    Nets  2000   10    Nets2000
6    Heat  2004    6    Heat2004
7  Pacers  2003   12  Pacers2003

вы можете столкнуться с ошибками, если ваш столбец без индекса имеет ячейки с NaN.

print df1

    Team   Year  foo
0   Hawks  2001    5
1   Hawks  2004    4
2    Nets  1987    3
3    Nets  1988    6
4    Nets  2001    8
5    Nets  2000   10
6    Heat  2004    6
7  Pacers  2003   12
8 Problem  2112  NaN


print df2

     Team  Year  foo
0  Pacers  2003   12
1    Heat  2004    6
2    Nets  1988    6
3 Problem  2112  NaN

new = df1.merge(df2,on=['Team','Year'],how='left')
print new[new.foo_y.isnull()]

     Team  Year  foo_x  foo_y
0   Hawks  2001      5    NaN
1   Hawks  2004      4    NaN
2    Nets  1987      3    NaN
4    Nets  2001      8    NaN
5    Nets  2000     10    NaN
6 Problem  2112    NaN    NaN

проблемная команда в 2112 не имеет значения для foo в любой таблице. Таким образом, левое соединение здесь ложно вернет эту строку, которая соответствует в обоих кадрах данных, как не присутствующая в правом кадре данных.

устранение:

что я делаю, это добавить уникальный столбец во внутренний фрейм данных и установить значение для всех строк. Затем, когда вы присоединитесь, вы можете проверить, если этот столбец является NaN для внутренней таблицы, чтобы найти уникальные записи во внешней таблице.

df2['in_df2']='yes'

print df2

     Team  Year  foo  in_df2
0  Pacers  2003   12     yes
1    Heat  2004    6     yes
2    Nets  1988    6     yes
3 Problem  2112  NaN     yes


new = df1.merge(df2,on=['Team','Year'],how='left')
print new[new.in_df2.isnull()]

     Team  Year  foo_x  foo_y  in_df1  in_df2
0   Hawks  2001      5    NaN     yes     NaN
1   Hawks  2004      4    NaN     yes     NaN
2    Nets  1987      3    NaN     yes     NaN
4    Nets  2001      8    NaN     yes     NaN
5    Nets  2000     10    NaN     yes     NaN

NB. Строка проблемы теперь правильно отфильтрована, потому что она имеет значение для in_df2.

  Problem  2112    NaN    NaN     yes     yes

Рассмотрим Следующее:

  1. df_one является первым фреймом данных
  2. df_two является вторым фреймом данных

в настоящее время Первый Фрейм Данных и не во втором фрейме данных

решение: by индекс df = df_one[~df_one.index.isin(df_two.index)]

индекс может быть заменен на required колонки на котором вы хотите сделать исключение. В приведенном выше примере я использовал index в качестве ссылки между обоими Фреймы Данных

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