0
votes

Comment compter les occurrences de plusieurs chaînes par ligne dans un bloc de données dans R

J'ai une question pour laquelle je pensais avoir trouvé une solution, mais si je vérifie à la main, j'obtiens des chiffres. J'ai cherché dans d'autres citations, mais je n'ai pas pu obtenir exactement ce que je recherchais.

J'ai une base de données avec des agents pharmaceutiques. Chaque ligne est un sujet et jusqu'à 20 colonnes stockent un agent chacune. Ensuite, j'ai une liste d'agents qui peuvent être regroupés dans un seul but. Par exemple. bêta-bloquants. Ce que je voudrais faire, c'est parcourir chaque ligne pour compter si et combien, par exemple. bêta-bloquants ou statines qu'un sujet prend.

J'ai essayé avec:

> dat$betablock[1]
[1] 0

Je ne reçois pas d'avertissement mais cela ne compte pas les nombre correct d'occurrences.

Voici quelques exemples de données:

       Med1         Med2       Med3          Med4            Med5          Med6       Med7         Med8        Med9     Med10      Med11    Med12    Med13    Med14      Med15
1  AMLODIPIN     RAMIPRIL METOPROLOL                                                                                                                                           
2     PLAVIX  SIMVASTATIN MIRTAZAPIN                                                                                                                                           
3 BISOPROLOL    AMLODIPIN        ASS     VALSARTAN    CHLORALDURAT     Doxozosin TAMSULOSIN     CIPRAMIL                                                                       
4        ASS    ENALAPRIL L-THYROXIN       LITALIR         LITALIR     AMLODIPIN  CETIRIZIN          HCT        NACL    CARMEN PROTEIN 88 NOVALGIN                             
5        ASS ATORVASTATIN    FOSAMAX       CALCIUM        PANTOZOL NOVAMINSULFON                                                                                               
6        ASS      FRAGMIN  TORASEMID SPIRONOLACTON LORZAAR PROTECT       VESIKUR  ROCALTROL ATORVASTATIN PREDNISOLON LACTULOSE MIRTAZAPIN   LANTUS ACTRAPID PANTOZOL SALBUTAMOL
          Med16 Med17 Med18 Med19 Med20
1                                      
2                                      
3                                      
4                                      
5                                      
6 AMPHO MORONAL                        

Comme vous pouvez le voir dans la première ligne, troisième colonne, la chaîne 'METOPROLOL' est répertoriée . Mais quand j'appelle le résultat de ma boucle for pour le premier sujet, cela donne «0».

BETA = c("METOPROLOL", "BISOPROLOL", "NEBILET", "METOHEXAL", "SOTALEX",
         "QUERTO", "NEBIVOLOL", "CARVEDILOL", "METOPROLOLSUCCINAT", "BELOC")
for (i in 1:202) {
  dat$betablock[i] <- sum(str_count(meds[i,], BETA ))
} 

Des suggestions?


1 commentaires

Vous devrez peut-être effectuer une boucle dans l'autre sens ou utiliser paste (BETA, collapse = "|")


3 Réponses :


1
votes

Supposons que les données sur les éléments pharamcuétiques se trouvent dans un agents data.frame. Traduire les éléments des agents en valeurs logiques, avec TRUE présent lorsque l'élément est dans BETA

> agents = data.frame(x = c("a", "b", "c"), y = c("b", "c", "d")
> stringr::str_count(agents[1,], c("a", "b"))
[1] 0 0
> agents = data.frame(x = c("a", "b", "c"), y = c("b", "c", "d"), stringsAsFactors=FALSE)
> stringr::str_count(agents[1,], c("a", "b"))
[1] 1 1

Ensuite, le nombre de bêta-bloquants dans chaque ligne (sujet) est

> stringr::str_count(c("a", "aa", "ab"), "a")
[1] 1 2 1

À titre d'exemple de jouet, voici quelques agents et bêta-bloquants

> agents
  x y
1 a b
2 b c
3 c d
> found = agents
> found[] = unlist(agents) %in% beta
> found
      x     y
1  TRUE  TRUE
2  TRUE FALSE
3 FALSE FALSE
> rowSums(found)
[1] 2 1 0
> agents$beta_blockers = rowSums(found)
> agents
  x y beta_blockers
1 a b             2
2 b c             1
3 c d             0


2 commentaires

Merci beaucoup. Avez-vous des suggestions pour expliquer pourquoi mon code n'a pas fonctionné?


@Torsten J'ai ajouté quelques commentaires à la fin sur ce qu'aurait pu être le problème avec votre approche.



1
votes

EDIT:

Dans le code suivant, vous pouvez calculer la somme de chaque bêta-bloquant en BÊTA et la somme de tous les bêta-bloquants pour chaque individu (ligne).

< pre> XXX

Créé le 16/01/2020 par le package reprex (v0.3.0)


0 commentaires

1
votes

Si je comprends bien, l'OP a plusieurs listes d'agents qui peuvent être regroupées dans un seul but pas seulement une liste de bêta-bloquants. L'OP mentionne les statines, par ex. Le PO veut compter combien d'agents différents appartenant à chaque cluster sont pris par chaque sujet. Les décomptes pour chaque cluster d'agents doivent être ajoutés à chaque ligne.

Je suggère de calculer les sommes pour tous les clusters à la fois plutôt que de le faire manuellement liste par liste.

Pour cela, nous devons d'abord configurer un bloc de données avec le clustering:

dat <- structure(list(Med1 = c("AMLODIPIN", "PLAVIX", "BISOPROLOL", 
"ASS", "ASS", "ASS"), Med2 = c("RAMIPRIL", "SIMVASTATIN", "AMLODIPIN", 
"ENALAPRIL", "ATORVASTATIN", "FRAGMIN"), Med3 = c("METOPROLOL", 
"MIRTAZAPIN", "ASS", "L-THYROXIN", "FOSAMAX", "TORASEMID"), Med4 = c("", 
"", "VALSARTAN", "LITALIR", "CALCIUM", "SPIRONOLACTON"), Med5 = c("", 
"", "CHLORALDURAT", "LITALIR", "PANTOZOL", "LORZAAR PROTECT"), 
    Med6 = c("", "", "Doxozosin", "AMLODIPIN", "NOVAMINSULFON", 
    "VESIKUR"), Med7 = c("", "", "TAMSULOSIN", "CETIRIZIN", "", 
    "ROCALTROL"), Med8 = c("", "", "CIPRAMIL", "HCT", "", "ATORVASTATIN"
    ), Med9 = c("", "", "", "NACL", "", "PREDNISOLON"), Med10 = c("", 
    "", "", "CARMEN", "", "LACTULOSE"), Med11 = c("", "", "", 
    "PROTEIN 88", "", "MIRTAZAPIN"), Med12 = c("", "", "", "NOVALGIN", 
    "", "LANTUS"), Med13 = c("", "", "", "", "", "ACTRAPID"), 
    Med14 = c("", "", "", "", "", "PANTOZOL"), Med15 = c("", 
    "", "", "", "", "SALBUTAMOL"), Med16 = c("", "", "", "", 
    "", "AMPHO MORONAL")), class = "data.frame", row.names = c(NA, 
-6L))
cluster[taken, on = .(Agent)][
  , dcast(.SD, ID ~ Purpose, length)][
    dat, on = "ID"][
      , "NA" := NULL][]

Le cluster peut être créé, par exemple, par

   ID BETA STATIN       Med1         Med2       Med3          Med4            Med5          Med6       Med7         Med8
1:  1    1      0  AMLODIPIN     RAMIPRIL METOPROLOL                                                                    
2:  2    0      1     PLAVIX  SIMVASTATIN MIRTAZAPIN                                                                    
3:  3    1      0 BISOPROLOL    AMLODIPIN        ASS     VALSARTAN    CHLORALDURAT     Doxozosin TAMSULOSIN     CIPRAMIL
4:  4    0      0        ASS    ENALAPRIL L-THYROXIN       LITALIR         LITALIR     AMLODIPIN  CETIRIZIN          HCT
5:  5    0      1        ASS ATORVASTATIN    FOSAMAX       CALCIUM        PANTOZOL NOVAMINSULFON                        
6:  6    0      1        ASS      FRAGMIN  TORASEMID SPIRONOLACTON LORZAAR PROTECT       VESIKUR  ROCALTROL ATORVASTATIN

Pour compter les occurrences, nous devons rejoindre ou fusionner cette table avec la liste des agents que chaque sujet prend dat après que dat a été remodelé du format large au format long.

Alors que les données sont au format grand format de feuille de calcul , c'est-à-dire avec une ligne par sujet et de nombreuses colonnes, conviennent souvent à la saisie et à l'inspection des données, le format long de style base de données est souvent plus adapté au traitement des données.

taken <- unique(taken, by = c("ID", "Agent"))
   ID variable   Agent
1:  4     Med5 LITALIR

dat est modifié en ajoutant un numéro de ligne qui identifie chaque sujet, puis il est remodelé au format long en utilisant melt () . Les entrées manquantes ou vides sont supprimées et les noms des agents sont convertis en majuscules pour des raisons de cohérence.

Modifier Dans le format long, il est également facile de vérifier les agents en double par sujet

XXX

taken[duplicated(taken, by = c("ID", "Agent"))]

et supprimez les doublons:

    ID variable           Agent
 1:  1     Med1       AMLODIPIN
 2:  2     Med1          PLAVIX
 3:  3     Med1      BISOPROLOL
 4:  4     Med1             ASS
 5:  5     Med1             ASS
 6:  6     Med1             ASS
 7:  1     Med2        RAMIPRIL
 8:  2     Med2     SIMVASTATIN
 9:  3     Med2       AMLODIPIN
10:  4     Med2       ENALAPRIL
11:  5     Med2    ATORVASTATIN
12:  6     Med2         FRAGMIN
13:  1     Med3      METOPROLOL
14:  2     Med3      MIRTAZAPIN
15:  3     Med3             ASS
16:  4     Med3      L-THYROXIN
17:  5     Med3         FOSAMAX
18:  6     Med3       TORASEMID
19:  3     Med4       VALSARTAN
20:  4     Med4         LITALIR
21:  5     Med4         CALCIUM
22:  6     Med4   SPIRONOLACTON
23:  3     Med5    CHLORALDURAT
24:  4     Med5         LITALIR
25:  5     Med5        PANTOZOL
26:  6     Med5 LORZAAR PROTECT
27:  3     Med6       DOXOZOSIN
28:  4     Med6       AMLODIPIN
29:  5     Med6   NOVAMINSULFON
30:  6     Med6         VESIKUR
31:  3     Med7      TAMSULOSIN
32:  4     Med7       CETIRIZIN
33:  6     Med7       ROCALTROL
34:  3     Med8        CIPRAMIL
35:  4     Med8             HCT
36:  6     Med8    ATORVASTATIN
37:  4     Med9            NACL
38:  6     Med9     PREDNISOLON
39:  4    Med10          CARMEN
40:  6    Med10       LACTULOSE
41:  4    Med11      PROTEIN 88
42:  6    Med11      MIRTAZAPIN
43:  4    Med12        NOVALGIN
44:  6    Med12          LANTUS
45:  6    Med13        ACTRAPID
46:  6    Med14        PANTOZOL
47:  6    Med15      SALBUTAMOL
48:  6    Med16   AMPHO MORONAL
    ID variable           Agent

La dernière étape crée ce que je crois être le résultat attendu:

taken <- melt(setDT(dat)[, ID := .I], "ID", value.name = "Agent", na.rm = TRUE)[
  Agent != ""][
    , Agent := toupper(Agent)][]

Veuillez noter les colonnes supplémentaires avec les décomptes par cluster (en raison de l'espace limité, toutes les colonnes du résultat ne sont pas affichées ici). Ceci est créé par

library(data.table)
library(magrittr)
cluster <- list(
  BETA = c("METOPROLOL", "BISOPROLOL", "NEBILET", "METOHEXAL", "SOTALEX",
           "QUERTO", "NEBIVOLOL", "CARVEDILOL", "METOPROLOLSUCCINAT", "BELOC"),
  STATIN = c("ATORVASTATIN", "SIMVASTATIN", "LOVASTATIN", "PRAVASTATIN", 
           "FLUVASTATIN", "PITAVASTIN")
  ) %>% 
  lapply(data.table) %>% 
  rbindlist(idcol = "Purpose") %>% 
  setnames("V1", "Agent")

en utilisant les opérations suivantes:

  1. Rejoignez le cluster et pris pour ajouter Purpose
  2. Remodeler en grand format, une ligne par sujet et une colonne par objectif, comptant ainsi le nombre d'occurrences
  3. Joindre ce résultat avec les données d'origine dat
  4. Supprimer la colonne superflue des décomptes NA

Données

    Purpose              Agent
 1:    BETA         METOPROLOL
 2:    BETA         BISOPROLOL
 3:    BETA            NEBILET
 4:    BETA          METOHEXAL
 5:    BETA            SOTALEX
 6:    BETA             QUERTO
 7:    BETA          NEBIVOLOL
 8:    BETA         CARVEDILOL
 9:    BETA METOPROLOLSUCCINAT
10:    BETA              BELOC
11:  STATIN       ATORVASTATIN
12:  STATIN        SIMVASTATIN
13:  STATIN         LOVASTATIN
14:  STATIN        PRAVASTATIN
15:  STATIN        FLUVASTATIN
16:  STATIN         PITAVASTIN


2 commentaires

C'est absolument ce que je voulais avoir à la fin. Belle voie directe. Seulement, je dois admettre que mes connaissances en R ne sont pas assez étendues pour comprendre votre code. Mais merci beaucoup. J'ai remarqué qu'il y avait des doublons dans certains des sujets. Existe-t-il un moyen d'implémenter la vérification des doublons sur les données d'origine 'dat'? J'ai également remarqué que lorsque j'ajoutais plus de listes d'agents après la sixième liste, le nom de la liste n'était plus inclus dans le fichier «cluster». Y at-il une raison à cela?


Par défaut, print () limitera le nombre de lignes affichées à l'écran. Vous pouvez vérifier l'exhaustivité en regardant les dernières lignes avec tail (cluster) ou en comptant le nombre d'agents dans chaque groupe cluster [ .N, by = Purpose] .