R: указание добавленного суффикса для неверных имен переменных при использовании ".value" в функциях поворота tidyr? - PullRequest
1 голос
/ 16 июня 2020

У меня есть данные, из которых данные хранятся в «широкой» структуре, так что значения нескольких наблюдений по набору переменных хранятся в нескольких столбцах в одной строке. Я пытаюсь преобразовать свои данные в длинную структуру, используя tidyr::pivot_longer(). Однако я получаю сообщение об ошибке «Не удалось создать вывод из-за плохих имен». потому что один из столбцов в кадре данных, который я передаю функции поворота, идентичен по крайней мере одному из имен столбцов, которые pivot_longer() хочет создать, на основе передачи ".value" аргументу names_to.

Хотя эта ошибка позволяет избежать плохих имен, и один из вариантов - изменить имена в данных, которые я передаю на pivot_longer(), я пытаюсь найти способ избежать этого с помощью самой функции. Аргумент имен ремонта можно использовать для добавления числовых суффиксов в конец имен, чтобы избежать дублирования имен столбцов, но я пытаюсь добавить свои собственные строки вместо суффиксов.

В частности, мне интересно если есть способ использовать аргумент names_to для создания имен столбцов, которые позволяют избежать ошибки имен при использовании ".value". Мотивация для этого - избежать передачи вектора имен столбцов в names_to. В качестве альтернативы, это может быть случай, когда использование pivot_longer_spec может быть подходящим, однако я не уверен, как использовать эту функцию в сочетании с ".value".

Минимальный рабочий пример приведен ниже:

library(tidyr)
library(dplyr)

# Create example data
dat <- data.frame(
  foo_1a = 1:3,
  foo_1b = 1:3,
  foo_2a = 1:3,
  foo_2b = 1:3,
  bar_1a = 1:3,
  bar_1b = 1:3,
  bar_2a = 1:3,
  bar_2b = 1:3,
  cat = c("a","b","c"),
  dog = c("d","e","f")
)

# No error
dat %>% tidyr::pivot_longer(
  cols = ends_with(c("1a", "1b", "2a", "2b")),
  names_to = c(".value", "profile"),
  names_sep = "_"
)

# Add another variable that causes duplicate names
# when pivoted due to column name prefix
dat_fail <- dat %>% mutate(foo = 4:6)

# "Error: Failed to Create output due to bad names"
# because the function tries to create foo when it's
# already in the data.
dat_fail %>% tidyr::pivot_longer(
  cols = ends_with(c("1a", "1b", "2a", "2b")),
  names_to = c(".value", "profile"),
  names_sep = "_"
)

# Attempt to fix #1: doesn't produce error
# but fails because it does not create columns
# foo and bar and instead places foo and bar
# in the .valuefiller column.
dat_fail %>% tidyr::pivot_longer(
  cols = ends_with(c("1a", "1b", "2a", "2b")),
  names_to = c(paste0(".value", "filler"), "profile"),
  names_sep = "_"
)

# Attempt to fix #2: try passing "unique" to
# repair argument, but doesn't work. Even so,
# this would append numeric suffixes when
# I want to be able to specify the suffix myself.
# Not sure if this is a bug.
dat_fail %>% tidyr::pivot_longer_spec(
  cols = ends_with(c("1a", "1b", "2a", "2b")),
  names_to = c(".value", "profile"),
  names_sep = "_",
  names_repair = "unique"
)

# Error in tidyr::pivot_longer_spec(., cols = ends_with(c("1a", "1b", "2a",  :
# unused arguments (  cols = ends_with(c("1a", "1b", "2a", "2b")),
# names_to = c(".value", "profile"), names_sep = "_")

# Desired output

# Create example data
dat <- data.frame(
  cat = c("a","a","a","a","b","b","b","b","c","c","c","c")
  dog = c("d","d","d","d","e","e","e","e","f","f","f","f")
  foo = c(1,1,1,1,2,2,2,2,3,3,3,3),
  profile = rep(c("1a","1b","2a","2b"), 3),
  foo_suffix = c(4,4,4,4,5,5,5,5,6,6,6,6)
)

1 Ответ

3 голосов
/ 16 июня 2020

names_repair может принимать функцию, принимающую имена столбцов в качестве входных данных.

Мы можем использовать это для получения желаемого результата. Следующее - всего лишь пример и, вероятно, не самый лучший, но вы можете использовать или написать функцию, которая лучше адаптируется к вашему варианту использования:

library(tidyr)
library(dplyr)

# Create example data
dat <- data.frame(
  foo_1a = 1:3,
  foo_1b = 1:3,
  foo_2a = 1:3,
  foo_2b = 1:3,
  bar_1a = 1:3,
  bar_1b = 1:3,
  bar_2a = 1:3,
  bar_2b = 1:3,
  cat = c("a","b","c"),
  dog = c("d","e","f")
)

dat_fail <- dat %>% mutate(foo = 4:6)

dat_fail %>% 
  pivot_longer(
    cols = ends_with(c("1a", "1b", "2a", "2b")),
    names_sep = '_',
    names_to = c(".value", "profile"),
    names_repair = ~ {
      .x[duplicated(.x, fromLast = TRUE)] <- paste(.x[duplicated(.x, fromLast = TRUE)], 'suffix', sep = '_')
      .x
      }
  )
#> New names:
#> * foo -> foo_suffix
#> # A tibble: 12 x 6
#>    cat   dog   foo_suffix profile   foo   bar
#>    <fct> <fct>      <int> <chr>   <int> <int>
#>  1 a     d              4 1a          1     1
#>  2 a     d              4 1b          1     1
#>  3 a     d              4 2a          1     1
#>  4 a     d              4 2b          1     1
#>  5 b     e              5 1a          2     2
#>  6 b     e              5 1b          2     2
#>  7 b     e              5 2a          2     2
#>  8 b     e              5 2b          2     2
#>  9 c     f              6 1a          3     3
#> 10 c     f              6 1b          3     3
#> 11 c     f              6 2a          3     3
#> 12 c     f              6 2b          3     3

Создано 16.06.2020 пакет REPEX (v0.3.0)

...