Pandas: фильтрация для уникальных строк в 2 столбцах

Вопрос:

У меня два DataFrames:

Interactor 1    Interactor 2   Interaction Type
Q99459          Q14204         MI:0914(association)
Q96G01          Q14203         MI:0914(association)
P01106          Q9H0S4         MI:0914(association)
Q9HAU4          P0CG47         MI:0414(enzymatic reaction)
O95786          Q14790         MI:0915(physical association)
... (90000 rows)

а также

Gene    UniProt ID
ABI1    Q8IZP0
ABL1    P00519
AKT1    P31749
AP2A1   O95782
AP2B1   P63010
... (244 rows)

Я хочу сделать следующее:

  1. Удалите все строки, где столбец Interaction Type в df1 отличается от набора частичных строк
  2. Удалите все строки, где Interactor 1 совпадает с Interactor 2
  3. Удалите любые строки, в которых любой из Interactor 1 или Interactor 2 НЕ находится в df2 UniProt ID df2 UniProt ID df2
  4. Удалите все повторяющиеся строки
  5. (Проблема здесь) Удалите строки, в которых обнаружено зеркальное взаимодействие, но сохраняйте один

На самом деле, последняя проблема – проблема. Я попытаюсь объяснить, что я имею в виду. Пара взаимодействует с двумя столбцами Interactor. Удаление повторяющихся пар взаимодействий (4) легко, но не зеркальные версии. Например, зеркальная пара взаимодействий будет выглядеть так:

Interactor 1     Interactor 2
Q123             Q456
Q456             Q123

Этого я не хочу. Или, скорее, я хочу только ОДИН из них, но неважно, что. Как мне это сделать? У меня есть следующий код, который делает точки (1) – (4) достаточно легко, но я не могу понять, как это сделать (5)…

# Read data
input_file = 'Interaction lists/PrimesDB PPI.xlsx'
data = pd.read_excel(input_file, sheetname='Sheet 1')
data = data[['Interactor 1', 'Interactor 2', 'Interaction Type']]

# Filter: interaction types
data = data[data['Interaction Type'].str.contains(
'MI:0407|MI:0915|MI:0203|MI:0217')]

# Filter: self-interactions
data = data[data['Interactor 1'] != data['Interactor 2']]

# Filter: included genes
genes = pd.read_excel('Interaction lists/PrimesDB PPI (filtered).xlsx',
sheetname='Gene list')
data = data[data['Interactor 1'].isin(genes['UniProt ID'])]
data = data[data['Interactor 2'].isin(genes['UniProt ID'])]

# Filter: unique interactions
unique = data.drop_duplicates(cols=['Interactor 1', 'Interactor 2')

Лучший ответ:

Для вашего пятого элемента, удаляя повторяющиеся пары, вы можете попробовать что-то вроде следующего, используя метод select в DataFrame. Он возвращает DataFrame, содержащий строку, которую вы хотите удалить (при условии, что дубликаты, которые вы хотите удалить, где “интерактор 2” лексикографически больше, чем “интерактор 1”,

Фильтр 1

#find duplicate pairs
filter = df.select(lambda x: (
                       (df['Interactor 2'] > df['Interactor 1']) &
                       (df['Interactor 2'] == df['Interactor 1'].loc[x]) & 
                       (df['Interactor 1'] == df['Interactor 2'].loc[x])
                   ).any())
#remove duplicate pairs
df.drop(filter.index, inplace=True)

Вы получите лучшую производительность, которую вы перебираете по более мелкой коллекции, и выполняете меньше работы над каждой строкой, поэтому перемещение первого сравнения из цикла улучшит производительность:

Фильтр 2

#find duplicate pairs
filter = (df['Interactor 2'] > df['Interactor 1']).select(lambda x: (
                       (df['Interactor 2'] == df['Interactor 1'].loc[x]) & 
                       (df['Interactor 1'] == df['Interactor 2'].loc[x])
                   ).any())
#remove duplicate pairs
df.drop(filter.index, inplace=True)

Чтобы проверить, я использую этот источник данных.

import pandas as pd
url = "http://biodev.extra.cea.fr/interoporc/files/study4932/srcInteractionsUsed.txt"
i1, i2 = 'ProteinAcA', 'ProteinAcB'
df1 = pd.read_table(url)  #1470 x 7 rows
df2 = df1.ix[:10].copy(deep=True) #11 x 7 rows
df2[i1] = df1.ix[:10][i2]
df2[i2] = df1.ix[:10][i1]
df2.index = range(1481,1492) 
df = pd.concat([df1, df2]) #1481 x 7 rows
filter = df[df[i1] > df[i2]].select(lambda x: (
                           (df[i2] == df[i1].loc[x]) & 
                           (df[i1] == df[i2].loc[x])).any() )

или

def FilterMirroredDuplicates(dataFrame, col1, col2):
    df = dataFrame[dataFrame[col1] > dataFrame[col2]]
    return df.select(lambda x: ((dataFrame[col2] == df[col1].loc[x]) & (dataFrame[col1] == df[col2].loc[x])).any()) 
filter = FilteredMirrorDuplicates(df, i1, i2)  #11 x 7 rows

Функция FilterMirroredDuplicates выполняет то же самое, что и оператор select над ним. Работая над этим, я обнаружил, что вышеприведенный фильтр 2 не генерирует соответствующий набор индексов. Вышеупомянутая формулировка или функция должны решить вашу проблему.

Имейте в виду, что использование selectO (n ^ 2). Но я не могу придумать никаких лучших средств для выполнения этой проверки.

Оцените статью
TechArks.Ru
Добавить комментарий