2017-09-06 5 views
1

Je suis relativement nouveau à R, et chaque fois que j'ai besoin de "remodeler" les données, je suis absolument déconcerté. J'ai des données qui ressemble à ceci:Réduire uniquement certaines variables à long format dans R

ont:

ID ever_smoked alcoholic  medication dosage 
1 1   no  no humira/adalimumab 40mg 
2 1   no  no  prednisone 15mg 
3 1   no  no  azathioprine 30mg 
4 1   no  no   rowasa 9mg 
5 2   yes  no   lialda 20mg 
6 2   yes  no mercaptopurine  1g 
7 2   yes  no   asacol 1600mg 

WANT:

ID ever_smoked alcoholic medication 
1 1   no  no humira/adalimumab, prednisone, azathioprine, rowasa 
2 2   yes  no lialda, mercaptopurine, asacol 

    dosage     most_recent_med  most_recent_dose 
1 40mg, 15mg, 30mg, 9mg rowasa    9mg 
2 20mg, 1g, 1600mg  asacol    1600mg 

(S'il vous plaît noter qu'il devrait être de 2 observations et 7 variables).

Essentiellement, je veux (1) seulement réduire quelques-unes des variables, et (2) conserver la première rangée des autres variables, et aussi (3) créer 2 nouvelles variables basées sur les dernières entrées de certains des variables.

Code

pour reproduire:

have <- data.frame(ID = c(1, 1, 1, 1, 2, 2, 2), 
    ever_smoked = c("no", "no", "no", "no", "yes", "yes", "yes"), 
    alcoholic = c("no", "no", "no", "no", "no", "no", "no"), 
    medication = c("humira/adalimumab", "prednisone", "azathioprine", "rowasa", "lialda", "mercaptopurine", "asacol"), 
    dosage = c("40mg", "15mg", "30mg", "9mg", "20mg", "1g", "1600mg"), stringsAsFactors = FALSE) 

want <- data.frame(ID = c(1, 2), 
    ever_smoked = c("no", "yes"), 
    alcoholic = c("no", "no"), 
    medication = c("humira/adalimumab, prednisone, azathioprine, rowasa", "lialda, mercaptopurine, asacol"), 
    dosage = c("40mg, 15mg, 30mg, 9mg", "20mg, 1g, 1600mg"), 
    most_recent_med = c("rowasa", "asacol"), 
    most_recent_dose = c("9mg", "1600mg"), stringsAsFactors = FALSE) 

Merci.

Répondre

3

C'est un processus sommaire, vous pouvez utiliser summarise_all et passer deux fonctions pour résumer chaque colonne: l'un pour réduire la colonne avec toString, un pour prendre la dernière ligne avec last:

have %>% 
    group_by(ID, ever_smoked, alcoholic) %>% 
    summarise_all(funs(toString(.), most_recent = last(.))) 

# A tibble: 2 x 7 
# Groups: ID, ever_smoked [?] 
#  ID ever_smoked alcoholic         medication_toString  dosage_toString medication_most_recent dosage_most_recent 
# <dbl>  <chr>  <chr>            <chr>     <chr>     <chr>    <chr> 
#1  1   no  no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg     rowasa    9mg 
#2  2   yes  no      lialda, mercaptopurine, asacol  20mg, 1g, 1600mg     asacol    1600mg 

Supposons ever_smoked et alcoolique sont uniques pour chaque ID ici.

4

Voici quelques approches différentes:

1) sqldf

library(sqldf) 
sqldf("select ID, 
       ever_smoked, 
       alcoholic, 
       group_concat(medication) as medication, 
       group_concat(dosage) as dosage, 
       medication as last_medication, 
       dosage as last_doage 
     from have 
     group by ID") 

donnant:

ID ever_smoked alcoholic          medication    dosage last_medication last_doage 
1 1   no  no humira/adalimumab,prednisone,azathioprine,rowasa 40mg,15mg,30mg,9mg   rowasa  9mg 
2 2   yes  no      lialda,mercaptopurine,asacol  20mg,1g,1600mg   asacol  1600mg 

2) données.Table

library(data.table) 
have_dt <- data.table(have) 
have_dt[, list(medication = toString(medication), 
       dosage = toString(dosage), 
       last_medication = medication[.N], 
       last_dosage = dosage[.N]), 
      by = "ID,ever_smoked,alcoholic"] 

donnant:

ID ever_smoked alcoholic           medication    dosage last_medication last_dosage 
1: 1   no  no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg   rowasa   9mg 
2: 2   yes  no      lialda, mercaptopurine, asacol  20mg, 1g, 1600mg   asacol  1600mg 

base 3) - par

do.call("rbind", by(have, have$ID, with, data.frame(
    ID = ID[1], 
    ever_smoked = ever_smoked[1], 
    alcoholic = alcoholic[1], 
    medication = toString(medication), 
    dosage = toString(dosage), 
    last_medication = tail(medication, 1), 
    last_dosage = tail(dosage, 1)))) 

donnant:

ID ever_smoked alcoholic           medication    dosage last_medication last_dosage 
1 1   no  no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg   rowasa   9mg 
2 2   yes  no      lialda, mercaptopurine, asacol  20mg, 1g, 1600mg   asacol  1600mg 

Notez que t son tour pourrait être écrit comme:

do.call("rbind", by(have, have$ID, function(x) with(x, data.frame(
    ID = ID[1], 
    ever_smoked = ever_smoked[1], 
    alcoholic = alcoholic[1], 
    medication = toString(medication), 
    dosage = toString(dosage), 
    last_medication = tail(medication, 1), 
    last_dosage = tail(dosage, 1))))) 

4) base - agrégat

aggregate(. ~ ID + ever_smoked + alcoholic, have, 
    function(x) c(values = toString(x), last = as.character(tail(x, 1)))) 

donner:

ID ever_smoked alcoholic         medication.values medication.last   dosage.values dosage.last 
1 1   no  no humira/adalimumab, prednisone, azathioprine, rowasa   rowasa 40mg, 15mg, 30mg, 9mg   9mg 
2 2   yes  no      lialda, mercaptopurine, asacol   asacol  20mg, 1g, 1600mg  1600mg 

Notez que cela renvoie une trame de données 2 x 5 dans lequel la les deux dernières colonnes sont chacune des matrices à 2 colonnes qui peuvent être plus commodes pour l'indexation que la forme aplatie mais si aplatie est préférée alors: do.call("data.frame", DF)