J'ai récemment publié une question sur la façon de créer un sous-ensemble à l'aide de R: Sous-ensemble de données dans R basé sur une liste spécifiée dans un vecteur (en utilisant une expression« commence par »ou équivalent)

L'utilisateur @Ric S a très gentiment fourni la réponse R à cette question. La solution R est:

library(dplyr)
df %>% 
  filter_at(vars(-ID), any_vars(grepl(paste(medications, collapse = "|"), .)))

Cependant, j'ai l'impression que Python peut être plus efficace en temps. Pour résumer, j'essaie d'identifier les statines prescrites par les participants dans un ensemble de données de plus d'un million de lignes et un sous-ensemble basé sur cela. J'ai une liste qui comprend tous les codes pour ces médicaments (j'en ai juste inventé quelques-uns à des fins de démonstration), et j'aimerais ensuite rechercher dans le cadre de données et le sous-attribuer à quiconque a un code de médicament qui "commence par " l'un des éléments de la liste. La boucle semble redondante dans l'exemple, mais j'exécuterai ce code pour quelques classes de médicaments.

Exemple d'ensemble de données, appelé meds_df:

     ID readcode_1 readcode_2 generic_name
1  1001       bxd1 1146785342  Simvastatin
2  1002       <NA>       <NA>         <NA>
3  1003       <NA>       <NA>  Pravastatin
4  1004       <NA>       <NA>         <NA>
5  1005       bxd4   45432344         <NA>
6  1006       <NA>       <NA>         <NA>
7  1007       <NA>       <NA>         <NA>
8  1008       <NA>       <NA>         <NA>
9  1009       <NA>       <NA>         <NA>
10 1010       bxde       <NA>         <NA>
11 1011       <NA>       <NA>         <NA>

Le résultat attendu étant:

     ID readcode_1 readcode_2 generic_name
1  1001       bxd1 1146785342  Simvastatin
3  1003       <NA>       <NA>  Pravastatin
5  1005       bxd4   45432344         <NA>
10 1010       bxde       <NA>         <NA>

Mon code jusqu'à présent basé sur d'autres questions de stackoverflow, je devrai également intégrer n'importe quel () ou un équivalent ici:

list_to_extract = ["bxd", "Simvastatin", "1146785342", "45432344", "Pravastatin"]
variable_list = ['statins']
for m in variable_list:
    print('extracting individuals prescribed %s' %m)
test = meds_df.loc[meds_df['readcode_1', 'readcode_2','generic_name'].str.startswith(list_to_extract, na=False)]
    print(test)

Erreur reçue:

KeyError: ('readcode_1', 'readcode_2','generic_name')

Toute aide sera fortement appréciée!

1
M_Oxford 4 juin 2020 à 21:48

3 réponses

Meilleure réponse

Tout d'abord, la syntaxe appropriée est meds_df[['readcode_1', 'readcode_2','generic_name']] (list des noms de colonnes dans une tranche d'index). C'est pourquoi vous obtenez un KeyError.

Pour répondre à votre question, voici une façon d'y parvenir:

# Updated to use tuple per David's suggestion
idx = pd.concat((med_df[col].astype(str).str.startswith(tuple(list_to_extract)) for col in ['readcode_1', 'readcode_2','generic_name']), axis=1).any(axis=1)

med_df.loc[idx]

Résultat:

      ID readcode_1    readcode_2 generic_name
1   1001       bxd1  1.146785e+09  Simvastatin
3   1003        NaN           NaN  Pravastatin
5   1005       bxd4  4.543234e+07          NaN
10  1010       bxde           NaN          NaN
2
r.ook 4 juin 2020 à 19:24

Vous pouvez le faire avec appliquer de cette manière:

list_to_extract = ["bxd", "Simvastatin", "1146785342", "45432344", "Pravastatin"]

bool_df = df[['readcode_1', 'readcode_2','generic_name']].apply(lambda x: x.str.startswith(tuple(list_to_extract), na=False), axis=1)

df.loc[bool_df[bool_df.any(axis=1)].index]

Production:

    ID  readcode_1  readcode_2  generic_name
1   1001    bxd1    1.146785e+09    Simvastatin
3   1003    NaN     NaN             Pravastatin
5   1005    bxd4    4.543234e+07    NaN
10  1010    bxde    NaN             NaN

Merci à r.ook d'avoir repéré une petite erreur

2
DavideBrex 5 juin 2020 à 07:04

Une solution alternative, où le traitement de la chaîne se produit dans vanilla python avant de recréer le dataframe:

list_to_extract = ["bxd", "Simvastatin", "1146785342", "45432344", "Pravastatin"]

cols_to_search = ['readcode_1', 'readcode_2','generic_name']

output = [(ID, *searchbox) 
          for ID, searchbox in zip(df.ID,df.filter(cols_to_search).to_numpy())
          if any([str(box).startswith(tuple(list_to_extract)) for box in searchbox])]

pd.DataFrame(output, columns = df.columns)


     ID readcode_1  readcode_2  generic_name
0   1001    bxd1     1.146785e+09   Simvastatin
1   1003    NaN      NaN            Pravastatin
2   1005    bxd4     4.543234e+07   NaN
3   1010    bxde     NaN            NaN
1
sammywemmy 4 juin 2020 à 23:57