Как удалить значения из одной серии pandas, которые являются общими для другой?

#python #pandas #indexing #series #drop

Вопрос:

Итак, у меня есть конкретная проблема, которую необходимо решить. Мне нужно удалить элементы, присутствующие в одной серии pandas (ser1), которые являются общими для другой серии pandas (ser2).

Я перепробовал кучу вещей, которые не работают, и самое близкое, что я смог найти, было с массивами, использующими функцию np.intersect1d(). Это работает для поиска общих значений, но когда я пытаюсь удалить индексы, равные этим значениям, я получаю кучу ошибок.

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

вот две серии:

 ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])
 

Результат должен быть:

 print(ser1)
0   1
1   2
2   3
 

Я уверен, что есть простое решение.

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

1. посмотрите на Series.isin()

Ответ №1:

Используйте .isin :

 >>> ser1[~ser1.isin(ser2)]
0    1
1    2
2    3
dtype: int64
 

Версия numpy .setdiff1d (и нет .intersect1d )

 >>> np.setdiff1d(ser1, ser2)
array([1, 2, 3])
 

Ответ №2:

Альтернатива numpy, np.isin

 import pandas as pd
import numpy as np

ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])

res = ser1[~np.isin(ser1, ser2)]
print(res)
 

Микро-бенчмарк

 import pandas as pd
import numpy as np
ser1 = pd.Series([1, 2, 3, 4, 5] * 100)
ser2 = pd.Series([4, 5, 6, 7, 8] * 10)
%timeit res = ser1[~np.isin(ser1, ser2)]
136 µs ± 2.56 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit res = ser1[~ser1.isin(ser2)]
209 µs ± 1.66 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit pd.Index(ser1).difference(ser2).to_series()
277 µs ± 1.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
 

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

1. Я думаю, вам также следует добавить набор python здесь

2. @sammywemmy Не уверен, как использовать set здесь, вы имеете в виду преобразование в set и обратно в series?

3. set(ser1).difference(ser2) … опасность с set заключается в том, что он неупорядочен

4. Работает, спасибо за ваше время!

5. Набор @sammywemmy выполняется очень быстро, но не упорядочен. Для тех же значений это дает 29us

Ответ №3:

Вы можете использовать set notation — я не уверен в скорости, хотя по сравнению с isin:

 pd.Index(ser1).difference(ser2).to_series()
Out[35]: 
1    1
2    2
3    3
dtype: int64
 

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

1. Это хорошо работает, спасибо, есть ли причина, по которой индекс новой серии не начинается с 0?

2. аааа… таким образом, индекс повторяется и как индекс, и как ряд. в рамках to_series метода вы можете вручную передать новый индекс. или просто reset_index

3. Для сброса индекса я использовал: ser1 = (pd.Index(ser1).difference(ser2).to_series()) ser1 = ser1.reset_index() print(ser1) и он дал мне это в качестве ответа : Name: alphabets, dtype: object index 0 0 1 1 1 2 2 2 3 3

4. используйте reset_index(drop=True)

5. Работает, спасибо за ваш ответ, очень признателен!