В R: tidyr разделяет и переворачивает значение в имя столбца, используя регулярное выражение

Я пытаюсь настроить tidyrpackage и борюсь с проблемой наличия переменной, которая является конкатенацией нескольких переменных. В приведенном ниже минимальном примере я хотел бы разделить переменную v2 на составляющие ее переменные v3 и v4, а затем изменить их, чтобы получить четыре переменные v1-v4.

require(plyr)
require(dplyr)
require(stringr)
require(tidyr)    
data <- 
      data.frame(
        v1=c(1,2),
        v2=c("v3 cheese; v4 200", "v3 ham; v4 150")) %>%
      tbl_df()

Если я разделю v2 на новый temp, я получу только v3:

mutate(data, 
      temp=unlist(sapply(str_split(data$v2, pattern=";"), "[", 1)))

  v1                v2      temp
1  1 v3 cheese; v4 200 v3 cheese
2  2    v3 ham; v4 150    v3 ham

Мои проблемы:

  • 1) Как разделить и качнуть v3 И v4 в качестве имен столбцов, используя tidyr?
  • 2) В моих реальных данных я не знаю (или их много) имена переменных, но они имеют структуру «значение var», и я хотел бы использовать некоторое регулярное выражение для их автоматической идентификации и качания, как в 1)

Вдохновился этим ответом SO, но не смог заставить его работать с кодом регулярного выражения для имен переменных.

ОБНОВЛЕНИЕ: Мой вывод будет примерно таким (v2 можно пропустить, поскольку теперь он избыточен с v3 и v4):

    v1  v2  v3  v4
1   1   v3 cheese; v4 200   cheese  200
2   2   v3 ham; v4 150  ham 150

person user3375672    schedule 18.03.2015    source источник
comment
Можете ли вы показать желаемый результат?   -  person David Arenburg    schedule 18.03.2015
comment
@David Arenburg: Конечно, см. ОБНОВЛЕНИЕ выше.   -  person user3375672    schedule 18.03.2015


Ответы (1)


Разделите данные с помощью ";", преобразуйте выходные данные разделения в длинную форму, снова разделите данные с помощью " " (но на этот раз в расширенной форме) и распределите значения в желаемой широкой форме.

Здесь используется «dplyr» + «tidyr» + «stringi»:

library(dplyr)
library(tidyr)
library(stringi)

data %>%
  mutate(v2 = stri_split_fixed(as.character(v2), ";")) %>%
  unnest(v2) %>%
  mutate(v2 = stri_trim_both(v2)) %>%
  separate(v2, into = c("var", "val")) %>%
  spread(var, val)
# Source: local data frame [2 x 3]
# 
#   v1     v3  v4
# 1  1 cheese 200
# 2  2    ham 150

В качестве альтернативы, используя cSplit из моего пакета "splitstackshape" (который в настоящее время не работает с tbl_dfs)

library(dplyr)
library(tidyr)
library(splitstackshape)

as.data.frame(data) %>%
  cSplit("v2", ";", "long") %>%
  cSplit("v2", " ") %>%
  spread(v2_1, v2_2) 
#    v1     v3  v4
# 1:  1 cheese 200
# 2:  2    ham 150
person A5C1D2H2I1M1N2O1R2T1    schedule 18.03.2015
comment
Хорошо, я не знал о пакетных строках. Какой формат вы получаете для v2 после stri_split_fixed ? - person user3375672; 18.03.2015
comment
@ user3375672, stri_split_fixed даст вам list, который мы преобразуем в длинную форму, используя unnest из tyr. - person A5C1D2H2I1M1N2O1R2T1; 18.03.2015
comment
Он отлично работает с игровыми данными, но в моих реальных данных я получаю сообщение об ошибке: повторяющиеся идентификаторы для строк (.....) после spread(). Кажется, что ошибка выдается для некоторых строк, где var одинаково (но другие столбцы разные, и, следовательно, «уникальный ()» не решает ее. Есть идеи? - person user3375672; 18.03.2015
comment
@ user3375672, какой подход вы используете? Первый или второй? Похоже, вам нужно будет создать уникальный идентификатор перед первым разделением. То есть я предполагаю, что сами ваши исходные данные имеют дублированные значения v1. - person A5C1D2H2I1M1N2O1R2T1; 18.03.2015
comment
Конечно! Решено mutate(id=rownames(.)). Идеально! - person user3375672; 18.03.2015