【问题标题】:How to apply function with multiple conditions on multiple columns to get new conditional columns in R如何在多个列上应用具有多个条件的函数以在 R 中获取新的条件列
【发布时间】:2021-05-25 10:02:21
【问题描述】:

大家好,这里是 R 菜鸟,

希望你们能帮我解决以下问题。

我需要根据原始列中的值多次将数据集中的多个列转换为新列。这意味着对于第一个转换,我使用第 1、2、3 列,如果满足某些条件,则输出结果是一个带有 1 或 0 的新列,对于第二个转换,我使用第 4、5、6 列,并且输出应该也可以是 1 或 0。我必须这样做 18 次。如果我手动估算变量,我已经编写了一个可以成功进行转换的函数,但我想一次将此函数应用于所有所需的列。我想要的输出是 18 个带有 0 和 1 的新列。最后,我将制作最后一列,如果 18 列中的任何一列为 1,则显示 1,否则显示 0。

    df <- data.frame(admiss1 = sample(seq(as.Date('1990/01/01'), as.Date('2000/01/01'), by="day"), 12),
                     admiss2 = sample(seq(as.Date('1990/01/01'), as.Date('2000/01/01'), by="day"), 12),
                     admiss3 = sample(seq(as.Date('1990/01/01'), as.Date('2000/01/01'), by="day"), 12),
                     visit1 = sample(seq(as.Date('1995/01/01'), as.Date('1996/01/01'), by="day"), 12),
                     visit2 = sample(seq(as.Date('1997/01/01'), as.Date('1998/01/01'), by="day"), 12),
                     reason1 = sample(3,12, replace = T),
                     reason2 = sample(3,12, replace = T),
                     reason3 = sample(3,12, replace = T))
    
    df$discharge1 <- df$admiss1 + 10
    df$discharge2 <- df$admiss2 + 10
    df$discharge3 <- df$admiss3 + 10
#every discharge date is 10 days after the admission date for the sake of this example
    
#now I have the following dataframe
#for the sake of it I included only 3 dates and reasons(instead of 18)
          admiss1    admiss2    admiss3     visit1     visit2 reason1 reason2 reason3 discharge1 discharge2 discharge3
    1  1990-03-12 1992-04-04 1998-07-31 1995-01-24 1997-10-07       2       1       3 1990-03-22 1992-04-14 1998-08-10
    2  1999-05-18 1990-11-25 1995-10-04 1995-03-06 1997-03-13       1       2       1 1999-05-28 1990-12-05 1995-10-14
    3  1993-07-16 1998-06-10 1991-07-05 1995-11-06 1997-11-15       1       1       2 1993-07-26 1998-06-20 1991-07-15
    4  1991-07-05 1992-06-17 1995-10-12 1995-05-14 1997-05-02       2       1       3 1991-07-15 1992-06-27 1995-10-22
    5  1995-08-16 1999-03-08 1992-04-03 1995-02-20 1997-01-03       1       3       3 1995-08-26 1999-03-18 1992-04-13
    6  1999-10-07 1991-12-26 1995-05-05 1995-10-24 1997-10-15       3       1       1 1999-10-17 1992-01-05 1995-05-15
    7  1998-03-18 1992-04-18 1993-12-31 1995-11-14 1997-06-14       3       2       2 1998-03-28 1992-04-28 1994-01-10
    8  1992-08-04 1991-09-16 1992-04-23 1995-05-29 1997-10-11       1       2       3 1992-08-14 1991-09-26 1992-05-03
    9  1997-02-20 1990-02-12 1998-03-08 1995-10-09 1997-12-29       1       1       3 1997-03-02 1990-02-22 1998-03-18
    10 1992-09-16 1997-06-16 1997-07-18 1995-12-11 1997-01-12       1       2       2 1992-09-26 1997-06-26 1997-07-28
    11 1991-01-25 1998-04-07 1999-07-02 1995-12-27 1997-05-28       3       2       1 1991-02-04 1998-04-17 1999-07-12
    12 1996-02-25 1993-03-30 1997-06-25 1995-09-07 1997-10-18       1       3       2 1996-03-06 1993-04-09 1997-07-05
    
    admissdate <- function(admis, dis, rsn, vis1, vis2){
      xnew <- ifelse(df[eval(substitute(admis))] >= df[eval(substitute(vis1))] & df[eval(substitute(dis))] <= df[eval(substitute(vis2))] & df[eval(substitute(rsn))] == 2, 1, 0)
      xnew <- ifelse(df[eval(substitute(admis))] >= df[eval(substitute(vis1))] & df[eval(substitute(admis))] <= df[eval(substitute(vis2))] & df[eval(substitute(dis))] >= df[eval(substitute(vis2))] & df[eval(substitute(rsn))] == 2, 1, xnew)
      return(xnew)
    }

我编写了这个函数,如果条件为真,则生成 1,如果条件为假,则生成 0。

-条件1:入院日期和出院日期在访视1和访视2之间+入院原因为2。

-条件2:入院日期在就诊1之后,就诊2之前,出院日期在就诊2之后,入院原因2。

如果这些条件为真,它应该返回 1,如果这些条件为假,它应该返回 0。最终,我将得到 18 个带有 1 或 0 的新变量,并将它们组合成一个变量,其中包含访问 1 和访问 2 之间的准入(原因 2)。

如果我手动估算变量名,它会起作用,但我不能让它同时适用于所有变量。我尝试用所有入院日期、出院日期和原因制作一个字符串向量,并尝试用 mapply 对其进行转换,但这不起作用。

    admiss <- paste0(rep("admiss", 3), 1:3)
    discharge <- paste0(rep("discharge", 3), 1:3)
    reason <- paste0(rep("reason", 3), 1:3)
    visit1 <- rep("visit1",3)
    visit2 <- rep("visit2",3)
    
    mapply(admissdate, admis = admiss, dis = discharge, rsn = reason, vis1 = visit1, vis2 = visit2)

我也考虑过 lapply,但在这里你必须定义一个 X = ...,我认为我不能使用它,因为我有多个要估算的列,如果我错了,请纠正我!

我也考虑过使用 for 循环,但我不知道如何在多个条件下使用它。

任何帮助将不胜感激!

【问题讨论】:

  • If I manually impute the variable names it will work。您能说明如何手动估算变量吗?另外,这个例子的预期输出是什么? 3 个新列 + 1 个带有 1 和 0 的其他列?
  • 所以如果我手动输入以下内容:'code' df$admis1

标签: r loops multiple-columns mapply


【解决方案1】:

您可以更改函数以接受值而不是列名。

admissdate <- function(admis, dis, rsn, vis1, vis2){
  xnew <- as.integer(admis >= vis1 & dis <= vis2 & rsn == 2)
  xnew <- ifelse(admis >= vis1 & admis <= vis2 & dis >= vis2 & rsn == 2, 1, xnew)
  return(xnew)
}

现在创建新列 -

admiss <- paste0("admiss", 1:3)
discharge <- paste0("discharge", 1:3)
reason <- paste0("reason", 1:3)
new_col <- paste0('newcol', 1:3)

df[new_col] <- Map(function(x, y, z) admissdate(x, y, z, df$visit1, df$visit2), 
                   df[admiss],df[discharge],df[reason])
#Additional column will be 1 if any of the value in the new column is 1.
df$result <- as.integer(rowSums(df[new_col]) > 0)
df

【讨论】:

  • 这正是我想要的!非常感谢。那么Map在这种情况下的作用是什么,是一种将一个函数应用到多个列的方式吗?
  • Mapmapply 相同。唯一的区别是Map 总是返回一个列表,而mapply 可能会也可能不会返回列表。 Map 实际上是 mapply 的包装。
猜你喜欢
  • 2020-12-04
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多