【问题标题】:R function to mutate multiple columnsR函数改变多列
【发布时间】:2021-11-05 05:17:07
【问题描述】:

我正在处理药物注册数据。我想计算诊断前开具的口服药物剂量。在示例数据中,dia_date 代表诊断日期,ddd 代表剂量。

df1 <- tribble(
  ~id,  ~drug_group,    ~drug_type, ~prescribed_date,   ~dia_date,  ~ddd,
  1,    "A",    "oral",     2010,   2020,   1,  
  1,    "B",    "non-oral", 2011,   2020,   2,  
  2,    "A",    "oral",     2019,   2020,   1,  
  2,    "B",    "oral",     2019,   2020,   1,  
  2,    "C",    "oral",     2008,   2021,   2,  
  3,    "A",    "oral",     2021,   2020,   2,  
  3,    "C",    "non-oral", 2009,   2021,   2,  
  4,    "A",    "oral",     2010,   2020,   NA )

输出应该是这样的


df2 <- tribble(
~id,    ~drug_group,    ~drug_type, ~prescribed_date,   ~dia_date,  ~ddd,   ~ddd_a, ~ddd_b, ~ddd_c,
1,  "A",    "oral",     2010,   2020,   1,  1,  0,  0,
1,  "B",    "non-oral", 2011,   2020,   2,  0,  0,  0,
2,  "A",    "oral",     2019,   2020,   1,  1,  0,  0,
2,  "B",    "oral",     2019,   2020,   1,  0,  1,  0,
2,  "C",    "oral",     2008,   2021,   2,  0,  0,  2,
3,  "A",    "oral",     2021,   2020,   2,  0,  0,  0,
3,  "C",    "non-oral", 2009,   2021,   2,  0,  0,  0,
4,  "A",    "oral",     2010,   2020,   NA, 0,  0,  0 )

在实际数据集中,药物组数>20。 我尝试了以下代码,但无济于事。


##Attempt1
 for (col in c("a","b","c")){
  ddd_= paste0("ddd_",col)
  df1[,ddd_] = df1$ddd
}

for (i in c("ddd_a","ddd_b","ddd_c")){
  if (df1$prescribed_date>df1$dia_date & df1$drug_group!="oral"){
    df1[,i] <- 0
  }
}

##Attempt2
for (col in c("a","b","c")){
  ddd_= paste0("ddd_",col)
  df1[,ddd_] = df1$ddd
}
f <- function (x) ifelse(df1$prescribed_date>df1$dia_date & df1$drug_group!="oral",0,x)
df1 %>% mutate(across(starts_with("ddd_")), f)

如果有任何帮助,我将不胜感激。

【问题讨论】:

  • 为什么id 3 at drug_group "A" 没有 2 剂 ddd_a
  • 在诊断 (2020) 后开具了 id 3 的药物组“A” (2021)。这就是为什么它被排除在外,因为我想要诊断前的药物暴露。
  • 编辑我的帖子以符合该要求

标签: r for-loop dplyr


【解决方案1】:

使用reshape2dcast

df1 %>%
  dcast(id+drug_group+drug_type+prescribed_date+dia_date+ddd ~ drug_group, length) %>%
  mutate_at(.funs = list(ddd = ~.*ddd*(drug_type == "oral")*(prescribed_date <= dia_date)), .vars = vars(A:C)) %>%
  select(-c(A:C))

产生:

  id drug_group drug_type prescribed_date dia_date ddd A_ddd B_ddd C_ddd
1  1          A      oral            2010     2020   1     1     0     0
2  1          B  non-oral            2011     2020   2     0     0     0
3  2          A      oral            2019     2020   1     1     0     0
4  2          B      oral            2019     2020   1     0     1     0
5  2          C      oral            2008     2021   2     0     0     2
6  3          A      oral            2021     2020   2     0     0     0
7  3          C  non-oral            2009     2021   2     0     0     0
8  4          A      oral            2010     2020  NA    NA    NA    NA

【讨论】:

  • 我尝试了建议的代码。但我得到了 Error in eval(variables_names, envir = envir, enclos = baseenv()) : object 'A' not found 。能否请你帮忙?我也想知道mutate_at函数中``` ~.*ddd* ```的意思。
  • 所以关于mutate_at,没有*ddd,你得到的只是0和1,是drug_type A(1)还是不是A(0),乘以你获得剂量,如果是 NA,您将获得 NA。我不确定您遇到的错误,您能检查一下我是发生在mutate_at 还是select 中吗?
  • 感谢您的解释。经检查,错误发生在mutate_at
  • 嗯,真实表有没有额外的列?还是drug_groups 不同? dcast 应该为每个唯一的drug_group 创建一个列,其中包括您提供的表中的“A”。尝试仅运行 dcast 以查看创建了哪些列
  • 当我尝试使用 ``` .vars=c(7:9)``` 而不是 ``` .vars=var(A:C), I got the desired output. Direct variable name .vars=var(A: C)```似乎不起作用。如何使用直接变量名?
【解决方案2】:

你可以试试这个-

library(dplyr)
library(tidyr)

df1 %>%
  #Keep data for only 'oral' drug type
  filter(drug_type == 'oral') %>%
  #Create temporary columns
  mutate(temp = ddd, 
         name = paste0('ddd_', drug_group)) %>%
  #Keep selected columns
  select(id, drug_group, ddd:name) %>%
  #Get the data in wide format
  pivot_wider(names_from = name, values_from = temp, values_fill = 0) %>%
  #Join with the original dataset
  right_join(df1, by = c('id', 'drug_group', 'ddd')) %>%
  #Replace NA with 0
  replace(is.na(.), 0)

#     id drug_group   ddd ddd_A ddd_B ddd_C drug_type prescribed_date dia_date
#  <dbl> <chr>      <dbl> <dbl> <dbl> <dbl> <chr>               <dbl>    <dbl>
#1     1 A              1     1     0     0 oral                 2010     2020
#2     2 A              1     1     0     0 oral                 2019     2020
#3     2 B              1     0     1     0 oral                 2019     2020
#4     2 C              2     0     0     2 oral                 2008     2021
#5     3 A              2     2     0     0 oral                 2021     2020
#6     4 A              0     0     0     0 oral                 2010     2020
#7     1 B              2     0     0     0 non-oral             2011     2020
#8     3 C              2     0     0     0 non-oral             2009     2021

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    相关资源
    最近更新 更多