首页 > 解决方案 > 如何使用 toString 创建字符串?

问题描述

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

我已经尝试了函数paste,paste0toString,但我无法达到预期的结果。

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

标签: rdata.tabletostring

解决方案


你很接近,只需添加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事先创建 s。)

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

说明: diff计算每个值与其前一个值的差值;我们在 if is的条件下应用ifelse(它是矢量化的ifand ) 。elsediff< 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列中的列中的值,您可以使用以下代码省略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列,我们想要与我们实现的实际行长度的seq影响。因为我们不希望这些值已经出现在列中,所以我们在应用之前使用. 给了我们一个向量,因为我们不想要一列类列表。scMapnewmatch scdata.dt$newtoStringunlist

查看?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"))

推荐阅读