Сравнивая все столбцы на двух панелях данных панд, чтобы получить разницу - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть два кадра данных панд.Допустим, первый из них master

ID  COL1    COL2
1   A       AA
2   B       BB
3   C       CC
4   D       DD

И еще один source

ID  COL1    COL2
1   A       ZZ
2   B       BB
3   YY      CC
5   G       GG
6   H       HH

Очевидно, длина может быть разной, и разница может быть в нескольких столбцах.Однако структура будет такой же.Я хочу найти записи в source, которые либо являются новыми, либо отличаются от записей, доступных в master.То есть вывод, который я ищу, представляет собой фрейм данных:

ID  COL1    COL2
1   A       ZZ
3   YY      CC
5   G       GG
6   H       HH

Я пытался найти решения в:

Но ни один из них, похоже, не работает для меня.Это в основном пытается узнать, что нового.

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

вы можете создать маску и использовать boolean indexing:

# set index
source = source.set_index('ID')
master = master.set_index('ID')

# find any record across rows where source is not in master
mask = (~source.isin(master)).any(1)
# boolean indexing
source[mask]

   COL1 COL2
ID          
1     A   ZZ
3    YY   CC
5     G   GG
6     H   HH
0 голосов
/ 05 февраля 2019

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

  1. Выполните итерацию сравнений и добавьте их в новый фрейм данных.(Больше кода, более эффективная память)
  2. Создайте новый объединенный (внешний) фрейм данных и примените функцию для удаления дубликатов.(Меньше кода, но менее эффективно работает с памятью)

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

Решение 1: (учитывая, что идентификаторы уникальны, а не индекс)

list = source['ID'].tolist() #get a list of all the ids in source
results = pd.DataFrame(columns = source.columns.tolist()) #Creates an empty df with same columns
for id in list:
    if(~((source[id]['COL1'] == master[id]['COL1']) & (source[id]['COL2'] == master[id]['COL2']))):
    #Here we evaluate the cases where everything is equal and execute on negation of said statement (by using ~, which equates to NOT)
        results.append(source[id])

Решение 2:

results = source.merge(master, how = 'outer', on= source.columns.tolist()) #assuming both dfs have same columns
final_results = results.drop_duplicates(Keep = False) #this will drop all rows that are duplicated.
0 голосов
/ 05 февраля 2019

Используйте merge с indicator=True и outer join, затем фильтруйте и получайте только столбцы по df2.columns:

#specified columns in list
cols = ['COL1','COL2']
#all columns without ID
#cols = df.columns.difference(['ID'])
df = (df1.merge(df2, on=cols, how='outer', indicator=True, suffixes=('_',''))
         .query("_merge == 'right_only'")[df2.columns])
print (df)
    ID COL1 COL2
4  1.0    A   ZZ
5  3.0   YY   CC
6  5.0    G   GG
7  6.0    H   HH
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...