Как отфильтровать значения в столбце с общими значениями в другом общем и применить два условия при фильтрации

У меня есть такой фрейм данных

df = pd.DataFrame({'patient': ['patient1', 'patient1', 'patient1','patient2', 'patient2', 'patient3','patient3','patient4'], 
                   'gene':['TYR','TYR','TYR','TYR','TYR','TYR','TYR','TYR'],
                   'variant': ['buu', 'luu', 'stm','lol', 'bla', 'buu', 'lol','buu'],
                    'genotype': ['hom', 'het', 'hom','het', 'hom', 'het', 'het','het']})
df

 patient    gene    variant genotype
0   patient1    TYR buu hom
1   patient1    TYR luu het
2   patient1    TYR stm hom
3   patient2    TYR lol het
4   patient2    TYR bla hom
5   patient3    TYR buu het
6   patient3    TYR lol het
7   patient4    TYR buu het

Я хочу выявить пациентов, у которых есть buu и дополнительные варианты, НО не luu. Итак, ожидаемый результат должен быть таким

patient gene variant genotype

patient3  TYR     buu      het
patient3  TYR     lol      het

Как я могу это сделать?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
80
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

используя set операции:

# aggregate the variants as sets
g = df.groupby('patient')['variant'].agg(set)

# keep the patients with more than "buu" but not "luu"
keep = g.index[g.gt({'buu'}) & ~g.ge({'luu'})]
# ['patient3']

# index rows of the above patients
out = df[df['patient'].isin(keep)]

Выход:

    patient gene variant genotype
5  patient3  TYR     buu      het
6  patient3  TYR     lol      het

Промежуточные продукты:

g

patient
patient1    {buu, stm, luu}
patient2         {bla, lol}
patient3         {buu, lol}
patient4              {buu}
Name: variant, dtype: object


g.gt({'buu'})  # g > {'buu'}

patient
patient1     True
patient2    False
patient3     True
patient4    False
Name: variant, dtype: bool


~g.ge({'luu'}) # ~(g> = {'luu'})

patient
patient1    False
patient2     True
patient3     True
patient4     True
Name: variant, dtype: bool

используя groupby.agg

m = (
 df.assign(has_buu=df['variant'].eq('buu'),
           not_luu=df['variant'].ne('luu'),
           other=~df['variant'].isin(['buu', 'luu'])
          )
   .groupby('patient')
   .agg({'has_buu': 'any', 'not_luu': 'all', 'other': 'any'})
)

out = df[df['patient'].isin(m.index[m.all(axis=1)])]

Выход:

    patient gene variant genotype
5  patient3  TYR     buu      het
6  patient3  TYR     lol      het

Средний:

m

          has_buu  not_luu  other
patient                          
patient1     True    False   True
patient2    False     True   True
patient3     True     True   True
patient4     True     True  False

Были ли проблемы с моим ответом?

mozway 03.04.2023 16:33

Вероятно, существует однострочное решение, но я бы предпочел построить его, чтобы вы могли понять его логику. Вы хотите получить всех пациентов, у которых нет варианта «luu». В мире баз данных более простым подходом было бы получить все, что имеет «luu», и разделить его из исходного db.

1. Получить пациентов с вариантом «луу»:

patients = list(df[df['variant'] == 'luu']['patient'])

Это вернет список пациентов, у которых есть вариант «luu».

Получить все записи, принадлежащие другим пациентам:

df = df[~df.patient.isin(patients)]

За ваш вклад вы получите:

df
    patient gene variant genotype
3  patient2  TYR     lol      het
4  patient2  TYR     bla      hom
5  patient3  TYR     buu      het
6  patient3  TYR     lol      het
7  patient4  TYR     buu      het

С этого момента я не совсем уверен, как вы можете ожидать ожидаемого результата от «Я хочу идентифицировать пациентов, у которых есть buu и дополнительные варианты, НО не luu». Но если вы хотите получить сразу несколько выражений, вы можете сделать что-то вроде:

df[~df.patient.isin(patients)][df.genotype == 'het']

Для этого он вернет:

    patient gene variant genotype
3  patient2  TYR     lol      het
5  patient3  TYR     buu      het
6  patient3  TYR     lol      het
7  patient4  TYR     buu      het
Ответ принят как подходящий

Вы также можете попробовать следующее решение:

import pandas as pd

# First we filter out those groups that have only 1 observations
g = df.groupby('patient').filter(lambda x: len(x) > 1)

# Then we apply both of our desired conditions
m = (g.groupby('patient')['variant'].transform(lambda x: x.eq('buu').any() & (~ x.eq('luu').any())))

g.loc[m]

    patient gene variant genotype
5  patient3  TYR     buu      het
6  patient3  TYR     lol      het

Другие вопросы по теме