我正在尝试在for循环中使用嵌套的ifelse语句来创建一个新变量,其值基于因子变量(邮政编码列表)的出现频率。
新变量应根据邮政编码的频率(频率范围在1到4之间)返回预定义的数字系列。这些数字系列中的每个数字都必须以800结尾,并以200为增量递增,其起始点取决于每个邮政编码的频率:频率越高,起始增量200越低。
为此,我定义了一个for循环,在该循环中,我首先测量每个邮政编码的频率,然后测量一个嵌套的ifelse语句,并根据频率指定要分配给NewVar的每个数字序列。
这里写了一个我想要实现的直观小示例,我想将此示例应用于包含数百万个邮政编码的数据框。
所需结果:
Postcode NewVar
AA 600
AA 800
BB 400
BB 600
BB 800
CC 800
DD 200
DD 400
DD 600
DD 800
代码:
DF$NewVar <- 0
DF$NewVar <- for (i in levels(DF$Postcode[i]))
ifelse((table(DF$Postcode[i]) == 4), DF$NewVar[i] <- c(200,400,600,800),
(ifelse ((table(DF$Postcode[i]) == 3), DF$NewVar[i] <- c(400,600,800),
(ifelse ((table(DF$Postcode[i]) == 2), DF$NewVar[i] <- c(600,800),
DF$NewVar[i] <- c(800))))))
问题1:
首先,在运行整个代码时,我收到一条错误消息,指出替换中的行数与数据中的行数不匹配,而在手动检查时,情况并非如此(不匹配总是仅限1行)。
Error in `$<-.data.frame`(`*tmp*`, NewVar, value = c("0", "0", "0", :
replacement has 11 rows, data has 10.
问题2:
如果无法正常工作,请进行测试(超出范围):
当验证ifelse子句是否可以单独工作时(在循环外部),我看到NewVar的每一行仅复制了200的开始增量,因此它不会增加到800。这不是我的意思想要实现以下任何一个目标:
一次测试代码:
DF$NewVar[1:2] <- ifelse((sum(table(DF$Postcode)) == 2),
DF$NewVar[1:2] <- c(600,800), "NA")
结果(不需要):
Postcode NewVar
AA 200
AA 200
所需结果:
Postcode NewVar
AA 200
AA 400
注意:在尝试分配变量之前,我预定义了NewVar列,并且我已经检查了NA是否存在。
提前感谢您的时间。
答案 0 :(得分:1)
如果您愿意使用 dplyr 的一种方法:
library(dplyr)
DF <- structure(list(Postcode = c("AA", "AA", "BB", "BB", "BB", "CC",
"DD", "DD", "DD", "DD")), class = "data.frame", row.names = c(NA,
-10L))
vals <- c(200,400,600,800)
DF %>% group_by(Postcode) %>% mutate(NewVar = tail(vals,n()))
答案 1 :(得分:0)
为了完整起见,这是使用ave()
函数的基本R解决方案。
我们假设Postcode
是随机顺序的邮政编码的 vector :
Postcode
[1] "BB" "CC" "CC" "BB" "BB" "AA" "CC" "BB" "AA" "DD"
下面的代码创建一个包含Postcode
和NewVar
的data.frame:
data.frame(
Postcode,
NewVar = ave(Postcode, Postcode,
FUN = function(x) seq(to = 800, by = 200, length.out = length(x)))
)
Postcode NewVar 1 BB 200 2 CC 400 3 CC 600 4 BB 400 5 BB 600 6 AA 600 7 CC 800 8 BB 800 9 AA 800 10 DD 800
# create data
library(magrittr) # only used to improve readability
n_codes <- 4L
set.seed(1L)
Postcode <-
stringr::str_dup(LETTERS[1:n_codes], 2L) %>% # create codes
rep(times = sample(n_codes)) %>% # replicate randomly
sample() # re-order randomly