来自两个列表的R purrr按行查找

时间:2019-11-11 05:29:23

标签: r purrr

这是问题的简化版本,涉及更大,更复杂的输入。首先,我创建数据:

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

这些数据是来自三个人的12项测试的答案。 input是一个多级表,其中测试项目嵌套在每个人中。 input的列是:

  • person101102103人的ID号(每个人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的值,并用与{{1}相对应的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_numscale进行map2()调用中的mutate()编码,但是无法正常工作。

在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

如果将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中,可以使用stackmerge

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

数据

set.seed(1234)
input <- tibble(
   person = rep(101:103, each = 12),
   item = rep(1:12, 3),
   response = sample(1:4, 36, replace = TRUE))

答案 1 :(得分:1)

这是一个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 ) ][]

输出

#     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