这是问题的简化版本,涉及更大,更复杂的输入。首先,我创建数据:
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
人的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_num
和scale
进行map2()
调用中的mutate()
编码,但是无法正常工作。
在此先感谢您的帮助!
答案 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中,可以使用stack
和merge
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