如何使用 toString 创建字符串?

How can I create a string using toString?

我有一个包含 2 列的数据 table:类别和优先级。我使用 for 循环按以下方式对数据进行分类:

我已经尝试使用 pastepaste0toString 函数,但我无法达到预期的结果。

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 循环的情况下执行此操作。 (您不需要事先创建 NAs。)

data.dt$new <- 
  with(data.dt, ifelse(c(NA, diff(priority)) < 0, category, c(NA, category)))

解释: diff 计算每个值与其前一个值的差值;我们在 diff< 0.

的条件下应用 ifelse(向量化 ifelse
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 列中的值,您可以使用以下代码省略 matches:

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 列,我们需要 sequences sc 以及我们用 [= 实现的实际行的长度34=]。因为我们不希望这些值已经出现在 new 列中,所以我们在应用 toString 之前 match scdata.dt$newunlist 给了我们一个向量,因为我们不需要 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"))