R Извлечение значений из фрейма данных с векторами - PullRequest
0 голосов
/ 02 июля 2018

Я надеюсь, что мой вопрос не является дубликатом, но я действительно не мог найти то, что мне нужно. Я нырнул в dplyr и даже прошел курс data.table из DataCamp, но не могу это исправить. Может быть, что-то с видом?

У меня есть этот df:

set.seed(1964)
df<-data.frame(id = c( "XEY", "NZH", "DYE", "JNF", "LHH", "WNB"),
           q_1 = sample(5,6, replace = TRUE),
           q_2 = sample(5,6, replace = TRUE),
           q_3 = sample(5,6, replace = TRUE),
           q_4 = sample(5,6, replace = TRUE),
           q_5 = sample(5,6, replace = TRUE))

Так что мой df выглядит так:

enter image description here

Далее у меня есть два вектора с id (строки-индикаторы) и q (номера вопроса), подобные этим:

id <- c("XEY", "DYE", "JNF", "DYE", "XEY", "LHH", "WNB", "JNF" )
question <- c("val_1", "val_1","val_3","val_3","val_3", "val_4", "val_4", "val_5")

Я хочу извлечь значения из df, используя два вектора, чтобы получить вывод, подобный этому:

enter image description here

Я много чего пробовал, чтобы извлечь значения, но продолжаю получать ошибки. Я пробовал такие вещи, как:

df[id == (id[1]), (question[1])]
df[id == id[1], question[1]]

Странно то, что пакет data.table, похоже, принимает 'запись строки'. Потому что:

df[id == (id[1]),]

возвращает значение a для строки "XEY":

    id q_1 q_2 q_3 q_4 q_5
1: XEY   5   1   5   4   1

Но как сделать трюк для правильного обозначения столбца, используя мой вектор?

Извините за этот очень простой вопрос, спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

В базе R вы можете сделать следующее.

Value <- diag(as.matrix(df[match(id, df$id), sub("val", "q", question)]))
result <- data.frame(id, Question = sub("val", "q", question), Value)
result
#   id Question Value
#1 XEY      q_1     5
#2 DYE      q_1     1
#3 JNF      q_3     2
#4 DYE      q_3     1
#5 XEY      q_3     5
#6 LHH      q_4     2
#7 WNB      q_4     2
#8 JNF      q_5     3

Редактировать.

Увидев ответ @ Nicolas2, используя inner_join, я решил попробовать merge. Но для этого мне понадобится функция melt из внешнего пакета reshape2.

df2 <- data.frame(id, question = sub("val", "q", question))
df3 <- reshape2::melt(df, id.vars = "id")
names(df3)[2] <- "question"
result2 <- merge(df2, df3)
result2
#   id question value
#1 DYE      q_1     1
#2 DYE      q_3     1
#3 JNF      q_3     2
#4 JNF      q_5     3
#5 LHH      q_4     2
#6 WNB      q_4     2
#7 XEY      q_1     5
#8 XEY      q_3     5

Результат тот же, с другим порядком строк.

0 голосов
/ 02 июля 2018

Вы можете сделать это с Tidyr. Я добавляю stringsAsFactors = FALSE к вашему df, чтобы избежать предупреждения во время соединения.

set.seed(1964)
df<-data.frame(id = c( "XEY", "NZH", "DYE", "JNF", "LHH", "WNB"),
       q_1 = sample(5,6, replace = TRUE),
       q_2 = sample(5,6, replace = TRUE),
       q_3 = sample(5,6, replace = TRUE),
       q_4 = sample(5,6, replace = TRUE),
       q_5 = sample(5,6, replace = TRUE),stringsAsFactors=FALSE)
id <- c("XEY", "DYE", "JNF", "DYE", "XEY", "LHH", "WNB", "JNF" )
question <- c("q_1", "q_1","q_3","q_3","q_3", "q_4", "q_4", "q_5")

library(tidyr)
df2 <- data.frame(id,question,stringsAsFactors=FALSE)
df %>% gather(k,Value,-id) %>% inner_join(df2,by="id") %>% filter(question==k) %>% arrange(question) %>%
    select(-k)
...