Subset dataframe in R based on a list specified in a vector (using a 'starts with' expression or equivalent)

怎甘沉沦 提交于 2020-06-17 03:43:08

问题


I am trying to identify any participant taking statins in a dataset of over 1 million rows and subset based on this. I have a vector that includes all the codes for these medications (I've just made a few up for demonstration purposes), and I would next like to create a function that searches through the dataframe and identifies any case that has a medication code that "starts with" any of the characters listed in the df. The df looks like this:

     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>

Ideally, I'd like the end product to look like this:

     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>

Here is my code so far (doesn't currently work)

#create vector with list of medication codes of interest
medications <- c("bxd", "Simvastatin", "1146785342", "45432344", "Pravastatin")

# look through all columns (apart from IDs in first column) and if any of them start with the codes listed in the medications vector, return a 1
df$statin_prescribed <- apply(df[, -1], 1, function(x) {
  if(any(x %in% startsWith(x, medications))) {
    return(1)
  } else {
    return(0)
  }
})

# subset to include only individuals prescribed statins
df <- subset(df, statin_prescribed == 1)

The part that doesn't seem to work is startsWith(x, statin).

Please let me know if you have any suggestions and additional, whether there is alternative code that may be more time efficient!


回答1:


This is a solution using the dplyr package

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

Small explanation: we are asking to filter all those rows where at least one variable (excluding ID) starts with one of the values inside medications

Output

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

Another solution in base R with a similar rationale is the following

df[apply(df[,-1], 1, function(x) {any(grepl(paste(medications, collapse = "|"), x))}),]

Output is the same (except row index which I believe is not relevant)
#      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>

After some benchmarking tests, the base R solution seems to be around 5x faster than the dplyr one. So I suggest you to use the base R solution if time efficiency is your main concern.

microbenchmark::microbenchmark(
  df %>% filter_at(vars(-ID), any_vars(grepl(paste(medications, collapse = "|"), .))),
  df[apply(df[,-1], 1, function(x) {any(grepl(paste(medications, collapse = "|"), x))}),],
  times = 100
)

# Unit: microseconds
#                                                                                             # expr    min
#         df %>% filter_at(vars(-ID), any_vars(grepl(paste(medications,      collapse = "|"), .))) 1958.4
#  df[apply(df[, -1], 1, function(x) {     any(grepl(paste(medications, collapse = "|"), x)) }), ]  341.7
#       lq     mean  median      uq    max neval
#  1989.55 2146.993 2041.30 2149.05 7851.1   100
#   352.50  405.972  380.25  401.55 2154.0   100


来源:https://stackoverflow.com/questions/62195183/subset-dataframe-in-r-based-on-a-list-specified-in-a-vector-using-a-starts-wit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!