Как элегантно удалить идентифицированные записи с помощью панд?

#python #pandas #dataframe #numpy #pandas-groupby

Вопрос:

У меня есть фрейм данных pandas, как показано ниже

 df = pd.DataFrame({'subject_id': [101,102,103,201,202],
                  'test_id':[21,21,np.nan,24,25],
                  'test_name':['A','B',np.nan,'D','E'],
                  'invalid_condition':[0,0,0,0,1]})
 

Я хотел бы определить проблемы в данных на основе приведенных ниже условий и отбросить их

Хотя я могу идентифицировать их с помощью приведенного ниже кода, я не уверен, как их удалить

 subject_with_no_test_info = len(df.groupby('subject_id').filter(lambda x: x['test_id'].count() == 0))*100/len(df)
test_id_diff_names = len(df.groupby('test_id').filter(lambda x: x['test_name'].nunique() > 1))*100/len(df)
invalid_condition = len(df[df['invalid_condition']==1])*100/len(df)
data_inconsistencies_df = pd.DataFrame([[subject_with_no_test_info,test_id_diff_names,invalid_condition]],columns = ['subject_with_no_test_info','test_id_diff_names','invalid_condition'])
 

Это дает мне результат, как показано ниже

введите описание изображения здесь

но теперь я хочу удалить те записи, которые вносят вклад 20%, 40% and 20% в каждую колонку в data_incosistencies_df?

Есть ли элегантный и эффективный способ удалить эти записи из фрейма данных?

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

1. затем вместо вычисления процента возьмите индексы строк, где эти 3 условия удовлетворяют

Ответ №1:

Попробуй:

 d1=df.groupby('subject_id').filter(lambda x: x['test_id'].count() == 0)
d2=df.groupby('test_id').filter(lambda x: x['test_name'].nunique() > 1)
d3=df[df['invalid_condition']==1]
#your conditions

data_inconsistencies_df = pd.DataFrame([[(len(d1)*100/len(df)),(len(d2)*100/len(df)),(len(d3)*100/len(df))]],columns = ['subject_with_no_test_info','test_id_diff_names','invalid_condition'])
#created dataframe to show percentages

d2=d2.drop_duplicates('test_id',keep='last')
          #^your sub condition
          #(We don't drop  101, because we keep = first of duplicate test ids)
to_drop=pd.concat([d1,d2,d3]).index
#concatinating 3 dataframes to grab the index of the rows which are going to drop
 

Окончательно:

 df=df.drop(to_drop)
#dropping those indexes
 

Выход из df :

   subject_id    test_id     test_name   invalid_condition
0   101         21.0            A           0
3   201         24.0            D           0
 

Выход из data_inconsistencies_df :

   subject_with_no_test_info     test_id_diff_names  invalid_condition
0          20.0                         40.0            20.0