HNSKD
HNSKD

Reputation: 1644

Unlist data frame column and pasting them together

I have a dataframe as defined below:

df <- structure(list(ID = 1:19, MEDICATION = c("0", "NOVOMIX 26 BF, 20 D", 
                                               "NOVOMIX 14 D", "NOVOMIX 34 BF 22 D", "MIXTARD 52 BF 20 D", "MIXTARD 40 BF 24 D", 
                                               "MIXTARD 10 BF 8 D", "MIXTARD 42 BF 24 D", "MIXTARD 20 BF 18 D", 
                                               "MIXTARD 82 BF 46 D", "MIXTARD 14 BF 10 D", "NOVOMIX 15 BF 15 D", 
                                               "MIXTARD", NA, "MIXTARD 10 BF 4 D", "NOVOMIX", "MIXTARD --> NOVOMIX", 
                                               "NOT GIVEN ANY DIABETES MEDICATION INPATIENT PATIENT NORMALLY ON METFORMIN", 
                                               "GIVEN ASPART")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -19L), .Names = c("ID", "MEDICATION"))

I would like to extract all the medications (i.e. NOVOMIX, MIXTARD, METFORMIN, ASPART from the MEDICATION variable in the dataframe and paste them together. I wrote my code as follows:

library(tidyverse)
library(rebus)
df %>%
      mutate(MEDICATION2 = str_extract_all(MEDICATION, pattern = 
                           or1(c("NOVOMIX", "MIXTARD", "METFORMIN", "ASPART")))) %>%
      unnest(MEDICATION2) %>%
      group_by(ID) %>%
      mutate(MEDICATION2 = str_c(unlist(MEDICATION2), collapse = " - ")) %>%
      slice(1)

My expected output is:

df_out <- structure(list(ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16, 17, 18, 19), MEDICATION = c("0", "NOVOMIX 26 BF, 20 D", 
"NOVOMIX 14 D", "NOVOMIX 34 BF 22 D", "MIXTARD 52 BF 20 D", "MIXTARD 40 BF 24 D", 
"MIXTARD 10 BF 8 D", "MIXTARD 42 BF 24 D", "MIXTARD 20 BF 18 D", 
"MIXTARD 82 BF 46 D", "MIXTARD 14 BF 10 D", "NOVOMIX 15 BF 15 D", 
"MIXTARD", NA, "MIXTARD 10 BF 4 D", "NOVOMIX", "MIXTARD --> NOVOMIX", 
"NOT GIVEN ANY DIABETES MEDICATION INPATIENT PATIENT NORMALLY ON METFORMIN", 
"GIVEN ASPART"), MEDICATION2 = c(NA, "NOVOMIX", "NOVOMIX", "NOVOMIX", 
"MIXTARD", "MIXTARD", "MIXTARD", "MIXTARD", "MIXTARD", "MIXTARD", 
"MIXTARD", "NOVOMIX", "MIXTARD", NA, "MIXTARD", "NOVOMIX", "MIXTARD - NOVOMIX", 
"METFORMIN", "ASPART")), .Names = c("ID", "MEDICATION", "MEDICATION2"
), row.names = c(NA, -19L), class = "data.frame")

The problem is the code removed the row with MEDICATION == 0 and I think my code is too long for a simple extraction of strings. I would like to ask for help if you know how this code can be shorten (if possible).

Upvotes: 2

Views: 370

Answers (1)

Ronak Shah
Ronak Shah

Reputation: 389047

We can use stri_extract_all_regex from the stringi package to extract all the words which matches the pattern.

library(stringi)
med_pattern <- c("NOVOMIX|MIXTARD|METFORMIN|ASPART")
df$MEDICATION2 <- stri_extract_all_regex(df$MEDICATION, pattern = med_pattern)

As mentioned by @mt1022, the new column is a list. We may paste them together with

df$MEDICATION2<-paste(stri_extract_all_regex(df$MEDICATION,pattern = med_pattern)) 

However, it will not give some unwanted characters for lists with more than 1 element. This should give you the expected output.

chars <- stri_extract_all_regex(df$MEDICATION, pattern = med_pattern)
df$MEDICATION2 <- sapply(chars, paste, collapse = "-")
df$MEDICATION2

#[1] "NA"              "NOVOMIX"         "NOVOMIX"         "NOVOMIX"        
#[5] "MIXTARD"         "MIXTARD"         "MIXTARD"         "MIXTARD"        
#[9] "MIXTARD"         "MIXTARD"         "MIXTARD"         "NOVOMIX"        
#[13] "MIXTARD"         "NA"              "MIXTARD"         "NOVOMIX"        
#[17] "MIXTARD-NOVOMIX" "METFORMIN"       "ASPART" 

You can also do this in single line :

df$MEDICATION2 <- sapply(stri_extract_all_regex(df$MEDICATION, 
                         pattern = med_pattern), paste, collapse = "-")

Upvotes: 3

Related Questions