Проверьте многозначное дублирование в панд

#python #pandas #dataframe

Вопрос:

Входные

У меня есть фрейм данных с несколькими столбцами.

 proof_path = 

   #1  X  Y  #2 X_  Z  #3  W Z_  #4 W_ Y_
0  p1  a  b  p2  a  c  p2  a  c  p3  a  b
1  p1  a  b  p2  a  c  p3  a  c  p1  a  b
2  p1  a  b  p2  a  d  p3  e  d  p4  e  b
 

В приведенном выше фрейме данных я хочу проверить, дублируется ли каждая строка между [#1, X, Y] , [#2, X_, Z] , [#3, W, Z_] , и [#4, W_, Y_] .

Например, в строках, соответствующих индексу 0, [#2, X_, Z] и [#3, W_, Z_] перекрывающихся с [P2, a, c] . Кроме того, [#1, X, Y] и [#4, W_, Y_] в строке, соответствующей индексу 1, перекрываются [P1, a, b] . Я собираюсь удалить строки, которые перекрываются между этими несколькими значениями, из этого фрейма данных.

Мой желаемый результат таков

выход

 proof_path = 

   #1  X  Y  #2 X_  Z  #3  W Z_  #4 W_ Y_
2  p1  a  b  p2  a  d  p3  e  d  p4  e  b
 

И я попытался сделать следующее.

 triple_size = 3
for depth in range(int(len(proof_path.columns)/triple_size)-1):
    for i in range(1, int(len(proof_path.columns)/triple_size)-depth):
        current_rComp = proof_path.iloc[:, depth*size:(depth 1)*triple_size]
        next_rComp = proof_path.iloc[:, (depth i)*size:(depth i 1)*triple_size]
        current_rComp.columns = ['pred', 'subj', 'obj']
        next_rComp.columns = ['pred', 'subj', 'obj']
        proof_path = proof_path[current_rComp.ne(next_rComp).any(axis=1)]
 

Хотя эти методы смогли достичь желаемых результатов, они неэффективны, генерируя подмножество proof_path для каждой итерации. Есть ли простой способ выполнить эти задачи?

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

1. Было бы проще, если бы вы сначала прочитали фрейм данных только в четыре столбца? например #1, X, Y , является ли первый столбец #2, X_, Z вторым и т. Д.

Ответ №1:

Чтобы избежать вложенных циклов, вы можете использовать наборы: для каждой строки поместите четыре тройки значений в набор. Количество элементов в наборе-это количество уникальных троек. Затем вы можете использовать это количество уникальных троек в качестве маски для выбора строк:

 import numpy as np

proof_path['n_unique_triples'] = 
    proof_path.apply(lambda row: len(set((tuple(row[0:3]),
                                          tuple(row[3:6]),
                                          tuple(row[6:9]),
                                          tuple(row[9:12])))), axis=1)
    
df_select = proof_path[proof_path.n_unique_triples == 4]
df_select
 
     #1  X   Y   #2  X_  Z   #3  W   Z_  #4  W_  Y_  n_unique_triples
2   p1  a   b   p2  a   d   p3  e   d   p4  e   b   4