R purrr построчный поиск из двух списков - PullRequest
0 голосов
/ 11 ноября 2019

Вот упрощенная версия проблемы, которая включает в себя более крупные и более сложные входные данные. Сначала я создаю данные:

input <- tibble(
  person = rep(101:103, each = 12),
  item = rep(1:12, 3),
  response = sample(1:4, 36, replace = T)
)

Эти данные являются ответами трех человек на тест из 12 пунктов. input - это многоуровневая таблица, в которой тестовые элементы вложены в каждого человека. Столбцы input:

  • person: идентификационные номера для лиц 101, 102 и 103 (12 строк для каждого человека)
  • item: тестовые задания 1-12 для каждого человека. Обратите внимание, как элементы вложены в каждого человека
  • response: оценка для каждого элемента

Тест разделен на четыре подшкалы, состоящие из трех элементов в каждом.

scale_assign <- list(1:3, 4:6, 7:9, 10:12)
scale_num <- 1:4

scale_assign - это четырехэлементный список, содержащий четыре набора элементов (выраженных в четырех числовых диапазонах): элементы 1-3 (подшкала 1), пункты 4-6 (подшкала 2), пункты 7-9 (подшкала 3) и позиции 10-12 (подшкала 4). scale_num - это числовой вектор из четырех элементов, содержащий числа (1-4), обозначающие четыре подшкалы.

Я хочу, чтобы R обработал input по строкам, создав новый столбец scale и заполняя его правильным значением scale_num для каждого элемента (то есть для каждого элемента подкласса назначения). В каждой строке R необходимо проверить значение item по диапазонам в scale_assign и заполнить scale значением scale_num, которое соответствует диапазону scale_assign для этого элемента.

Требуемый результат выглядит следующим образом:

# A tibble: 36 x 4
#      person  item response scale
#  1    101     1        4     1
#  2    101     2        2     1
#  3    101     3        4     1
#  4    101     4        4     2
#  5    101     5        4     2
#  6    101     6        4     2
#  7    101     7        3     3
#  8    101     8        2     3
#  9    101     9        4     3
# 10    101    10        1     4
# 11    101    11        1     4
# 12    101    12        4     4
# 13    102     1        1     1
# 14    102     2        3     1
# 15    102     3        1     1
# 16    102     4        1     2
# 17    102     5        3     2
# 18    102     6        3     2
# 19    102     7        4     3
# 20    102     8        1     3
# 21    102     9        3     3
# 22    102    10        4     4
# 23    102    11        3     4
# 24    102    12        3     4
# 25    103     1        4     1
# 26    103     2        1     1
# 27    103     3        2     1
# 28    103     4        2     2
# 29    103     5        4     2
# 30    103     6        1     2
# 31    103     7        4     3
# 32    103     8        4     3
# 33    103     9        1     3
# 34    103    10        4     4
# 35    103    11        1     4
# 36    103    12        2     4

Предпочитая решение tidyverse, я подумал, что это может быть заданием для purrr::map2(), потому что кажется, что он включает одновременную итерацию по списку из четырех элементовscale_assign и четырехэлементный вектор scale_num. Я пытался реализовать кодирование scale в вызове map2(), используя mutate() и case_when() для кодирования, но не смог заставить его работать.

Заранее спасибо за любую помощь!

Ответы [ 2 ]

3 голосов
/ 11 ноября 2019

Вместо того, чтобы выполнять эту операцию построчно и проверять каждое значение, было бы легко выполнить операцию соединения, если вы измените scale_assign на именованный список, преобразуете его в массив данных и выполните right_join с input кадром данных.

scale_assign <- list(1:3, 4:6, 7:9, 10:12)
names(scale_assign) <- 1:4

library(tidyverse)

enframe(scale_assign) %>%
   unnest(cols = value) %>%
   mutate_all(as.integer) %>%
   right_join(input, by = c("value" = "item"))


# A tibble: 36 x 4
#    name value person response
#   <int> <int>  <int>    <int>
# 1     1     1    101        4
# 2     1     2    101        4
# 3     1     3    101        2
# 4     2     4    101        2
# 5     2     5    101        1
# 6     2     6    101        4
# 7     3     7    101        3
# 8     3     8    101        1
# 9     3     9    101        1
#10     4    10    101        2
# … with 26 more rows

В базе R это можно сделать с помощью stack и merge

merge(input, stack(scale_assign), all.x = TRUE, by.x = "item", by.y = "values")

data

set.seed(1234)
input <- tibble(
   person = rep(101:103, each = 12),
   item = rep(1:12, 3),
   response = sample(1:4, 36, replace = TRUE))
0 голосов
/ 11 ноября 2019

Вот решение data.table, использующее update-join. По сути, это ответ @Ronak Shah Base-R, но с использованием пакета data.table (т.е. высокая производительность на больших наборах данных).

library(data.table)
#1. set inpus as data.table
#2. create a lookup-table using `stack( scale_assign )`, 
#  and make that also a data.table (using setDT() )
#3. left update join on item
setDT(input)[ setDT( stack( scale_assign ) ), 
                     scale := i.ind,
                     on = .( item = values ) ][]

output

#     person item response scale
#  1:    101    1        3     1
#  2:    101    2        4     1
#  3:    101    3        3     1
#  4:    101    4        2     2
#  5:    101    5        3     2
#  6:    101    6        4     2
#  7:    101    7        1     3
#  8:    101    8        3     3
#  9:    101    9        4     3
# 10:    101   10        2     4
# 11:    101   11        3     4
# 12:    101   12        4     4
# 13:    102    1        4     1
# 14:    102    2        2     1
# 15:    102    3        3     1
# 16:    102    4        2     2
# 17:    102    5        1     2
# 18:    102    6        4     2
# 19:    102    7        1     3
# 20:    102    8        3     3
# 21:    102    9        2     3
# 22:    102   10        1     4
# 23:    102   11        4     4
# 24:    102   12        3     4
# 25:    103    1        1     1
# 26:    103    2        1     1
# 27:    103    3        2     1
# 28:    103    4        1     2
# 29:    103    5        2     2
# 30:    103    6        4     2
# 31:    103    7        4     3
# 32:    103    8        2     3
# 33:    103    9        3     3
# 34:    103   10        2     4
# 35:    103   11        2     4
# 36:    103   12        2     4
#     person item response scale
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...