R - добавление числа к строке оставляет пробел перед одиночными цифрами - PullRequest
0 голосов
/ 25 октября 2018

Я написал функцию для добавления идентификатора к каждому символу в векторе.(_Instance1 и т. Д.) Однако, когда я запускаю свой код, я получаю пробел перед моими однозначными идентификаторами.Есть ли способ убрать пробел?Например, для вектора символов («Привет», «Привет») я получаю («Hi_Instance 1», «Hello_Instance 1»).Как только я доберусь до 10, все в порядке.Вот мой код:

convert <- function(x) {
df <- as.data.frame(x)
df <- df %>% mutate(dummy = row_number())
df <- df %>% group_by(x) %>% mutate(id = row_number()) %>% ungroup()
x = apply(df, 1, function(row) {paste(row['x'], '_Instance', row['id'], sep = '')})
df['id']= NULL

return(x)
}

1 Ответ

0 голосов
/ 25 октября 2018

Я не могу точно объяснить, почему это происходит ... но вот альтернатива, которая работает:

convert <- function(x) {
  df <- data_frame(x = as.character(x$x)) %>%
    group_by(x) %>%
    mutate(id = row_number()) %>%
    ungroup()
  paste(df[['x']], "_Instance", df[['id']], sep = "")
}

head(mutate(mtcars, x=cyl))
#     mpg cyl  disp  hp drat    wt  qsec vs am gear carb x
# 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 6
# 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 6
# 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 4
# 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 6
# 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 8
# 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 6

convert(mutate(mtcars, x=cyl))
#  [1] "6_Instance1"  "6_Instance2"  "4_Instance1"  "6_Instance3"  "8_Instance1"  "6_Instance4" 
#  [7] "8_Instance2"  "4_Instance2"  "4_Instance3"  "6_Instance5"  "6_Instance6"  "8_Instance3" 
# [13] "8_Instance4"  "8_Instance5"  "8_Instance6"  "8_Instance7"  "8_Instance8"  "4_Instance4" 
# [19] "4_Instance5"  "4_Instance6"  "4_Instance7"  "8_Instance9"  "8_Instance10" "8_Instance11"
# [25] "8_Instance12" "4_Instance8"  "4_Instance9"  "4_Instance10" "8_Instance13" "6_Instance7" 
# [31] "8_Instance14" "4_Instance11"

Улучшение: мне нравится сохранять такие искусственные ключи легко сортируемыми, но если вы попытаетесьотсортировав их, вы увидите, что компонент "id" не облегчает:

sort(convert(mutate(mtcars, x=cyl)))
#  [1] "4_Instance1"  "4_Instance10" "4_Instance11" "4_Instance2"  "4_Instance3"  "4_Instance4" 
#  [7] "4_Instance5"  "4_Instance6"  "4_Instance7"  "4_Instance8"  "4_Instance9"  "6_Instance1" 
# [13] "6_Instance2"  "6_Instance3"  "6_Instance4"  "6_Instance5"  "6_Instance6"  "6_Instance7" 
# [19] "8_Instance1"  "8_Instance10" "8_Instance11" "8_Instance12" "8_Instance13" "8_Instance14"
# [25] "8_Instance2"  "8_Instance3"  "8_Instance4"  "8_Instance5"  "8_Instance6"  "8_Instance7" 
# [31] "8_Instance8"  "8_Instance9" 

(Уведомление 1, 10, 11, 2, 3, ...)

Другая альтернативагде наибольшее целое число в группе определяет число ведущих нулей:

convert <- function(x) {
  df <- data_frame(x = as.character(x$x)) %>%
    group_by(x) %>%
    mutate(
      id = row_number(),
      id = sprintf(paste0("%0", max(nchar(as.character(id))), "d"), id)
    )
  paste(df[['x']], "_Instance", df[['id']], sep = "")
}
sort(convert(mutate(mtcars, x=cyl)))
#  [1] "4_Instance01" "4_Instance02" "4_Instance03" "4_Instance04" "4_Instance05" "4_Instance06"
#  [7] "4_Instance07" "4_Instance08" "4_Instance09" "4_Instance10" "4_Instance11" "6_Instance1" 
# [13] "6_Instance2"  "6_Instance3"  "6_Instance4"  "6_Instance5"  "6_Instance6"  "6_Instance7" 
# [19] "8_Instance01" "8_Instance02" "8_Instance03" "8_Instance04" "8_Instance05" "8_Instance06"
# [25] "8_Instance07" "8_Instance08" "8_Instance09" "8_Instance10" "8_Instance11" "8_Instance12"
# [31] "8_Instance13" "8_Instance14"

или вы можете сделать это глобально, а не только для каждой группы:

convert <- function(x) {
  df <- data_frame(x = as.character(x$x)) %>%
    group_by(x) %>%
    mutate(id = row_number()) %>%
    ungroup() %>%
    mutate(id = sprintf(paste0("%0", max(nchar(as.character(id))), "d"), id))
  paste(df[['x']], "_Instance", df[['id']], sep = "")
}
sort(convert(mutate(mtcars, x=cyl)))
#  [1] "4_Instance01" "4_Instance02" "4_Instance03" "4_Instance04" "4_Instance05" "4_Instance06"
#  [7] "4_Instance07" "4_Instance08" "4_Instance09" "4_Instance10" "4_Instance11" "6_Instance01"
# [13] "6_Instance02" "6_Instance03" "6_Instance04" "6_Instance05" "6_Instance06" "6_Instance07"
# [19] "8_Instance01" "8_Instance02" "8_Instance03" "8_Instance04" "8_Instance05" "8_Instance06"
# [25] "8_Instance07" "8_Instance08" "8_Instance09" "8_Instance10" "8_Instance11" "8_Instance12"
# [31] "8_Instance13" "8_Instance14"

(Они неТочная глобальная сортировка, но нумерацию можно считать более последовательной. На данный момент это отчасти эстетично.)

Некоторые комментарии об эффективности кода в вашем примере:

  • Поскольку вы этого не делаетевернуть df, вам не нужно удалять поле "id";понимать, что R передает кадр по значению , что означает, что вызывающая среда никогда не видит изменений в кадре
  • Использование apply(..., 1, ...) с data.frame выполнимо, но часто проблематично, особенноесли в кадре есть numeric, так как он конвертирует все.Если вы работаете с данными большого размера, это может потреблять много ресурсов.
  • Поскольку вы используете paste (или paste0), вы можете извлечь выгоду из его естественной векторизации вместо использования чего-то вроде apply чтобы идти строка за строкой.Постарайтесь использовать эту естественную векторизацию как можно больше в R, в противном случае обычно меньше эффективности и больше кода, чем необходимо.Знайте, что paste имеет два соответствующих аргумента: sep= и collapse=.Рассматривая его использование в моих функциях, вы можете думать о sep= как о комбинировании по столбцам, а collapse= как о объединении по строкам.Очевидно, я не хотел объединять строки, но не стесняйтесь проверить collapse="" в этой последней функции и посмотреть, что произойдет.(Подсказка: одна длинная строка.)
  • Не уверен, что делать из dummy ... создано, никогда не использовалось.
  • В общем, когда я использовал group_by, я предпочитаю чистить-up и ungroup() позже, но это при условии, что я буду использовать этот кадр снова.В этом случае рама одноразовая, поэтому вам технически не нужно ungroup.Я приветствую чистоту (и привычку) его использования, и время его вычисления составляет почти 0, но знаю, что это не влияет на производительность apply или paste.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...