多个 if 循环条件并在列中打印输出

Posted

技术标签:

【中文标题】多个 if 循环条件并在列中打印输出【英文标题】:multiple if loop condition and priting the output in a column 【发布时间】: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,注意到,但这里的数据必须是一个列表,这适用于数据框中的任何列表。 【参考方案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` 我正在将第一个数据帧的输出与第二个列进行比较数据框

以上是关于多个 if 循环条件并在列中打印输出的主要内容,如果未能解决你的问题,请参考以下文章

在列中显示终端输出以有效地查看更多输出

如何在c ++中为每个嵌套循环打印新列中的输出?

滚动百分位函数在列中输出 0?

为什么此代码在列中输出4321?

如何计算某些值在 SQL 表中出现的次数并在列中返回该数字?

将CSV写为输出而不是打印