【问题标题】:multiple if loop condition and priting the output in a column多个 if 循环条件并在列中打印输出
【发布时间】:2017-07-10 12:34:24
【问题描述】:

我有一个包含如下所示两列的数据集:

 x1     | x2
ontime  |ontime
Alate   |ontime
ontime  |Blate
Alate   |Blate

我想要的输出是

  x12
ontime
Alate
Blate
Alate

我试图编写多个 if 循环:

 df$x12<- if(df$x1=='Alate' & df$x2=='ontime')
 {
 print('Alate')
 }else if(df$x1=='ontime' & df$x2=='Blate')
 {
 print('Blate')
 }else if(df$x1=='Alate' & df$x2=='Blate')
 {
 print('Alate')
 }else 
 print('ontime')

但它不起作用,它只是为所有行打印“准时”并发出警告:

条件的长度 > 1,并且只使用第一个元素

【问题讨论】:

  • 因为if()没有向量化,可以尝试链接ifelse()或者使用mapply()
  • 只要do.call(pmin, df)character 向量(即stringsAsFactors = FALSE 在创建时指定)即可工作。
  • @DavidArenburg,您能解释一下这里的“pmin”是什么以及它是如何工作的吗?
  • 我刚刚发现了您的模式,您希望基本上按字母顺序对结果进行排序,即 'Alate' 始终排在第一位,然后是 'Blate',然后是 'ontime'。因此,我可以在整个 data.frame 上调用 pmin,因为 data.frames 只是列表。但这只是一个技巧,如果你问我,对于一般情况,最好使用@Adamm 介绍的子集方法
  • @DavidArenburg,注意到,但这里的数据必须是一个列表,这适用于数据框中的任何列表。

标签: r if-statement


【解决方案1】:

这种方法采用David's suggestion 来使用pmin(),但将其扩展为处理任意订单。

David 观察到Alate 总是先出现,然后是Blate,最后是ontime。但是,不能想当然地认为请求的顺序与字母顺序相同。但是通过使用有序因子,该方法可以扩展到任意阶:

library(data.table)
# Specify the priority
prio <- c("Alate", "Blate", "ontime")
# coerce to data.table, convert columns to ordered factors, using the same levels,
# pick the value with the higher priority (lower level number) 
data.table(DF)[, c("x1", "x2") := lapply(.SD, ordered, levels = prio)][, x12 := pmin(x1, x2)][]
       x1     x2    x12
1: ontime ontime ontime
2:  Alate ontime  Alate
3: ontime  Blate  Blate
4:  Alate  Blate  Alate

这种方法避免了嵌套的ifelse() 表达式或多次选择性更新。

数据

DF <- structure(list(x1 = c("ontime", "Alate", "ontime", "Alate"), 
x2 = c("ontime", "ontime", "Blate", "Blate")), .Names = c("x1", 
"x2"), row.names = c(NA, -4L), class = "data.frame")

【讨论】:

    【解决方案2】:

    链接ifelse()的一种方式:

    数据:

    x1 <- c("ontime", "Alate", "ontime", "Alate")
    x2 <- c("ontime", "ontime", "Blate", "Blate")
    df <- data.frame(x1, x2)
    > df
          x1     x2
    1 ontime ontime
    2  Alate ontime
    3 ontime  Blate
    4  Alate  Blate
    

    然后你可以写:

    df$x3 <- ifelse(x1 == "Alate" & x2 == "ontime", "Alate",
                    ifelse(x1 == "ontime" & x2 == "Blate", "Blate",
                           ifelse(x1 == "Alate" & x2 == "Blate", "Alate", "ontime")))
    
    > df
          x1     x2     x3
    1 ontime ontime ontime
    2  Alate ontime  Alate
    3 ontime  Blate  Blate
    4  Alate  Blate  Alate
    

    【讨论】:

    • 使用一个 ifelse 已经够糟糕了,使用 3 个嵌套的 ifelse 更糟糕,而且完全没有必要。
    • 谢谢大家,@Mbr Mbr,谢谢你的 mapply 选项,我学到了一些新东西,是的,if 循环有效
    • @DavidArenburg 是的,我一看到我的错误就删除了答案。
    【解决方案3】:

    首先,您应该使用dput 发布您的数据集示例。 至于您的代码,您必须知道 R 是矢量化的,因此会发出警告。 if 语句试图将df$x1 中的一个元素与'Alate' 等进行比较,但该向量有很多元素。解决方法是使用ifelse,是矢量化的。

    dat <- read.table(text = "
    x1|x2
    ontime|ontime
    Alate|ontime
    ontime|Blate
    Alate|Blate
    ", header = TRUE, sep = "|", stringsAsFactors = FALSE)
    
    dat$x12 <- ifelse(dat$x1=='Alate' & dat$x2=='ontime', 'Alate',
        ifelse(dat$x1=='ontime' & dat$x2=='Blate', 'Blate',
        ifelse(dat$x1=='Alate' & dat$x2=='Blate', 'Alate', 'ontime')))
    
    dat
    

    还请注意,我已更改数据框的名称,因为 df 已经是 R 函数的名称。

    【讨论】:

      【解决方案4】:

      您要使用的 If 语句仅适用于长度为 1 的逻辑向量。所以可能根本不要使用 if。

      x12 <- df$x1=='Alate' & df$x2=='ontime'
      df[x12, 'x12'] <- 'Alate'
      
      x12 <- df$x1=='ontime' & df$x2=='Blate'
      df[x12, 'x12'] <- 'Blate'
      
      x12 <- df$x1=='Alate' & df$x2=='Blate'
      df[x12, 'x12'] <- 'Alate'
      
      df[is.na(df)] <- 'ontime'
      
      > df
            x1     x2    x12
      1 ontime ontime ontime
      2  Alate ontime  Alate
      3 ontime  Blate  Blate
      4  Alate  Blate  Alate
      

      【讨论】:

      • 感谢您的解决,我试过了,它在输出中给了我“真”或“假”,前三行都有错误:#incorrect number of subscripts on matrix跨度>
      • &gt; typeof(dat) [1] "list"你有什么?
      • 所以你有字符向量,如果你输入我们需要数据框:x1 &lt;- c("ontime", "Alate", "ontime", "Alate") x2 &lt;- c("ontime", "ontime", "Blate", "Blate") df &lt;- data.frame(x1, x2) 我的代码应该可以工作。也可以转换 char 向量 ti 列表,但有点棘手。
      • 复制,另外我对另一个数据帧使用了相同的 ifelse 循环(通过 MBR MBR),但输出显示为双倍,两个数据帧的原始数据相同。是否可以?出于这个原因,它给了我错误的输出,并且输出是逻辑类型
      • 当我在第二个数据帧上使用您的代码时,它给出了一个错误`#arguments imply different number of rows: 444, 453` 我正在将第一个数据帧的输出与第二个列进行比较数据框
      猜你喜欢
      • 2021-10-18
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多