Я не могу точно объяснить, почему это происходит ... но вот альтернатива, которая работает:
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
.