Определить строки в двух фреймах данных pandas, которые частично совпадают

#pandas #dataframe #comparison #rows #partial

#pandas #фрейм данных #сравнение #строки #частичное

Вопрос:

Я пытаюсь добавить столбец к фрейму данных df1, в котором указывается, отображается ли строка в df1 во втором фрейме данных df2. Как правило, это было бы довольно просто, однако я действительно хочу, чтобы совпадение 4/5 учитывалось так же, как совпадение столбцов 5/5.

То есть запись в новом столбце, добавленном в df1, озаглавленная «In_df2», была бы равна 1, если бы было точное совпадение в 5 соответствующих столбцах (из 9) или совпадения в 4/5 соответствующих столбцов. Допустим, это df1 (с удаленными посторонними столбцами).

 df1_rows = [['555555555', 'M', 'Mike', 'Smith', '1970-01-01'], ['999999999', 'F', 'Jane', 'Won&', '1980-01-01'], ['111111111', 'M', 'Steve', 'Patel', '1990-01-01']]
df1 = pd.DataFrame(df1_rows, columns = ['SSN', 'sex', 'first_name', 'last_name', 'dob']) 


     SSN sex first_name last_name         dob
0  555555555   M       Mike     Smith  1970-01-01
1  999999999   F        Jane      Won&  1980-01-01
2  111111111   M      Steve     Patel  1990-01-01
  

И скажите, что это df2.

 df2_rows = [['222222222', 'F', 'Steve', 'Patel', '1990-01-01'], ['555555555', 'M', 'Mike', 'Smith', '1970-01-01'], ['999999999', 'F', 'Jeff', 'Won&', '1980-01-01']]
df2 = pd.DataFrame(df2_rows, columns = ['SSN', 'sex', 'first_name', 'last_name', 'dob'])
df2

     SSN sex first_name last_name         dob
0  222222222   F      Steve     Patel  1990-01-01
1  555555555   M       Mike     Smith  1970-01-01
2  999999999   F       Jeff      Won&  1980-01-01
  

Затем он должен вернуть следующее:

 df3_rows = [['555555555', 'M', 'Mike', 'Smith', '1970-01-01', 1], ['999999999', 'F', 'Jane', 'Won&', '1980-01-01', 1], ['111111111', 'M', 'Steve', 'Patel', '1990-01-01', 0]]
df3 = pd.DataFrame(df3_rows, columns = ['SSN', 'sex', 'first_name', 'last_name', 'dob', 'In_df2'])
df3

     SSN sex first_name last_name         dob  In_df2
0  555555555   M       Mike     Smith  1970-01-01       1
1  999999999   F       Jane      Won&  1980-01-01       1
2  111111111   M      Steve     Patel  1990-01-01       0
  

Столбец «In_df2» имеет 1 в строке «0», потому что в df2 есть точное совпадение со строкой «0» в df1. В строке «1» есть 1, потому что в df2 есть совпадение 4/5 для строки «1» в df1. В строке «2» есть 0, потому что в df2 для строки «2» в df1 есть только совпадение 3/5.

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

И последнее, вывод не обязательно должен быть столбцом, как я добавляю. Я действительно просто хочу идентифицировать все строки в df1, у которых нет партнера 4/5 или 5/5 в df2.

Спасибо за любые предложения!

Мой код:

 def row_compare(row1, row2):
    
    count = 0

    if row1.ssn == row2.ssn:
        count  = 1
    if row1.dob == row2.dob:
        count  = 1
    if row1.sex == row2.sex:
        count  = 1
    if row1.first_name == row2.first_name:
        count  = 1
    if row1.last_name== row2.last_name:
        count  = 1
        
    if count &&t;= 4:
        out = 1
    else:
        out = 0
        
    return out
  

за которым следует:

 def row_to_df_compare(row1, df):
    
    df['In_Other'] = df.apply(lambda row2 : row_compare(row1, row2), axis = 1)
    if df.sum().In_Other &&t; 0:
        out = 1
    else:
        out = 0
    return out
  

и, наконец, с помощью:

 df1['In_df2'] = df1.apply(lambda row : row_to_df_compare(row, df2), axis = 1)
  

Ответ №1:

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

 from itertools import combinations 

df1['n_duplicates'] = 0

for columns in combinations(df2.columns, 4):
    columns = list(columns)
    df_concat = pd.concat([df1[columns], df2[columns]], i&nore_index = True, sort = False).reset_index(drop=True)
    df1['n_duplicates']  = df_concat.duplicated(keep = False).astype(int).iloc[:df1.shape[0]]

df1_dedup = df1[df1['n_duplicates'] < 4]