如何使用 toString 创建字符串?
How can I create a string using toString?
我有一个包含 2 列的数据 table:类别和优先级。我使用 for 循环按以下方式对数据进行分类:
- 我检查实际值的优先级是否小于
上一个
- 我将类别的值保存在“
new
”列中。
- 我把category以前的值保存在列的字符串中
“
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
你很接近,只需添加 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
或者,您可以使用 diff
在没有 for
循环的情况下执行此操作。 (您不需要事先创建 NA
s。)
data.dt$new <-
with(data.dt, ifelse(c(NA, diff(priority)) < 0, category, c(NA, category)))
解释: diff
计算每个值与其前一个值的差值;我们在 diff
为 < 0
.
的条件下应用 ifelse
(向量化 if
和 else
)
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
uences sc
以及我们用 [= 实现的实际行的长度34=]。因为我们不希望这些值已经出现在 new
列中,所以我们在应用 toString
之前 match
sc
和 data.dt$new
。 unlist
给了我们一个向量,因为我们不需要 class 列表的一列。
查看 ?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"))
我有一个包含 2 列的数据 table:类别和优先级。我使用 for 循环按以下方式对数据进行分类:
- 我检查实际值的优先级是否小于 上一个
- 我将类别的值保存在“
new
”列中。 - 我把category以前的值保存在列的字符串中
“
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
你很接近,只需添加 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
或者,您可以使用 diff
在没有 for
循环的情况下执行此操作。 (您不需要事先创建 NA
s。)
data.dt$new <-
with(data.dt, ifelse(c(NA, diff(priority)) < 0, category, c(NA, category)))
解释: diff
计算每个值与其前一个值的差值;我们在 diff
为 < 0
.
ifelse
(向量化 if
和 else
)
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
uences sc
以及我们用 [= 实现的实际行的长度34=]。因为我们不希望这些值已经出现在 new
列中,所以我们在应用 toString
之前 match
sc
和 data.dt$new
。 unlist
给了我们一个向量,因为我们不需要 class 列表的一列。
查看 ?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"))