Как я могу создать строку, используя toString? - PullRequest
1 голос
/ 20 июня 2019

У меня есть таблица данных с 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

1 Ответ

2 голосов
/ 20 июня 2019

Вы были близки, просто добавьте 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 uences sc с длиной фактической строки, которую мы достигаем с Map. Поскольку мы не хотим, чтобы эти значения уже появлялись в столбце new, мы match sc с data.dt$new перед применением toString. unlist дает нам вектор, потому что нам не нужен столбец списка классов.

Просмотр ?Map показывает, что он последовательно применяет FUN ction к следующим двум объектам в том же порядке : 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"))
...