多个 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跨度>> typeof(dat) [1] "list"
你有什么?
所以你有字符向量,如果你输入我们需要数据框:x1 <- c("ontime", "Alate", "ontime", "Alate") x2 <- c("ontime", "ontime", "Blate", "Blate") df <- data.frame(x1, x2)
我的代码应该可以工作。也可以转换 char 向量 ti 列表,但有点棘手。
复制,另外我对另一个数据帧使用了相同的 ifelse 循环(通过 MBR MBR),但输出显示为双倍,两个数据帧的原始数据相同。是否可以?出于这个原因,它给了我错误的输出,并且输出是逻辑类型
当我在第二个数据帧上使用您的代码时,它给出了一个错误`#arguments imply different number of rows: 444, 453` 我正在将第一个数据帧的输出与第二个列进行比较数据框以上是关于多个 if 循环条件并在列中打印输出的主要内容,如果未能解决你的问题,请参考以下文章