我有一个包含2列的数据表:类别和优先级。我使用for循环以以下方式对数据进行分类:
new
”列中。rest
”。我已经尝试使用功能paste
,paste0
和toString
,但是我无法达到预期的效果。
priority <- c(3,2,1,4,5,6,7)
category <- c("a","b","c","d","e","f","g")
data.dt <- data.table(priority,category)
data.dt$new <- NA
data.dt$rest <- NA
for (i in 2:nrow(data.dt)){
if(data.dt$priority[i]<=data.dt$priority[i-1]){
data.dt$new[[i]] <- data.dt$category[i]
data.dt$rest[[i]] <- toString(data.dt$category[i-1])
}
else{
data.dt$new[[i]] <- data.dt$category[i-1]
data.dt$rest[[i]] <- toString(data.dt$category[i])
}
}
这是我的结果:
priority category new rest
1: 3 a <NA> <NA>
2: 2 b b a
3: 1 c c b
4: 4 d c d
5: 5 e d e
6: 6 f e f
7: 7 g f g
但是我想要以下一个:
priority category new rest
1: 3 a <NA> <NA>
2: 2 b b a
3: 1 c c a,b
4: 4 d c a,b,d
5: 5 e d a,b,d,e
6: 6 f e a,b,d,e,f
7: 7 g f a,b,d,e,f,g
答案 0 :(得分:2)
您接近了,只需添加1:x
序列(表示为#
)而不是单个值即可。
data.dt$new <- NA
data.dt$rest <- NA
for (i in 2:nrow(data.dt)) {
if(data.dt$priority[i] <= data.dt$priority[i-1]) {
data.dt$new[[i]] <- data.dt$category[i]
data.dt$rest[[i]] <- toString(data.dt$category[1:(i-1)]) #
}
else{
data.dt$new[[i]] <- data.dt$category[i-1]
data.dt$rest[[i]] <- toString(data.dt$category[1:i]) #
}
}
# priority category new rest
# 1: 3 a <NA> <NA>
# 2: 2 b b a
# 3: 1 c c a, b
# 4: 4 d c a, b, c, d
# 5: 5 e d a, b, c, d, e
# 6: 6 f e a, b, c, d, e, f
# 7: 7 g f a, b, c, d, e, f, g
或者,您可以使用for
,而无需进行diff
循环。 (您无需事先创建NA
。)
data.dt$new <-
with(data.dt, ifelse(c(NA, diff(priority)) < 0, category, c(NA, category)))
说明: diff
计算每个值与先前值的差;如果ifelse
为if
,我们将应用else
(向量化的diff
和< 0
)。
sl <- c(NA, Map(function(x) toString(data.dt$category[seq(x)]), seq(nrow(data.dt))))
data.dt$rest <- ifelse(c(NA, diff(data.dt$priority)) < 0, sl, sl[-1])
data.dt
# priority category new rest
# 1: 3 a <NA> NA
# 2: 2 b b a
# 3: 1 c c a, b
# 4: 4 d c a, b, c, d
# 5: 5 e d a, b, c, d, e
# 6: 6 f e a, b, c, d, e, f
# 7: 7 g f a, b, c, d, e, f, g
更新
要摆脱rest
列中出现的new
列中的值,可以使用以下代码省略match
es:
sc <- Map(function(x) c(data.dt$category[seq(x)]), seq(nrow(data.dt)))
data.dt$rest <- unlist(c(NA, Map(function(x, y)
toString(x[is.na(match(x, y))]), sc, data.dt$new)[-1]))
说明:对于rest
列,我们希望seq
的{{1}}带有我们用sc
实现的实际行的长度。因为我们不希望这些值已经出现在Map
列中,所以我们在应用new
之前将match
sc
与data.dt$new
一起使用。 toString
为我们提供了一个矢量,因为我们不需要一列类列表。
查看unlist
会发现它已按?Map
的顺序将FUN
部分依次应用于以下两个对象 :Map(FUN, x, y)
。结果收集在列表中。对于第四个元素,如下所示:
# Map(FUN, x, y)
(x <- sc[[4]])
# [1] "a" "b" "c" "d"
(y <- data.dt$new[[4]])
# [1] "c"
toString(x[is.na(match(x, y))]) # FUN
# [1] "a, b, d"
结果
data.dt
# priority category new rest
# 1 3 a <NA> <NA>
# 2 2 b b a
# 3 1 c c a, b
# 4 4 d c a, b, d
# 5 5 e d a, b, c, e
# 6 6 f e a, b, c, d, f
# 7 7 g f a, b, c, d, e, g
数据
data.dt <- structure(list(priority = c(3, 2, 1, 4, 5, 6, 7), category = c("a",
"b", "c", "d", "e", "f", "g")), row.names = c(NA, -7L), class = c("data.table",
"data.frame"))