编写函数以从 r 中的两个数据框中按变量名进行索引以查找值

writing function to index by variable name from two data frames in r to look up a value

我正在尝试编写一个函数来转换问卷的两个版本中的响应,根据响应将其编码为“是”或“否”。一些问题没有得到回答所以被编码为缺失

#example data

q1 <- c("column 2", "column 2", "column 1", NA, "column 1")
q2 <- c("column 1", "column 2", "column 2", NA, "column 1")
q3 <- c("column 1", "column 2", "column 1", "column 2", "column 1")
version <- c(1, 1, 2, 2, 1)
xdat <- data.frame(cbind(q1, q2, q3, version))

 >   xdat
        q1       q2       q3 version
1 column 2 column 1 column 1       1
2 column 2 column 2 column 2       1
3 column 1 column 2 column 1       2
4     <NA>     <NA> column 2       2
5 column 1 column 1 column 1       1

我创建了一个可能的响应数据框,其中包含每个版本的是或否响应的字符向量,以及每行的问题编号向量。

#make dataframe of values for converting the two versions of the questionnaire)
v1y <- c("column 2", "column 2", "column 1")
v1n <- c("column 1", "column 1", "column 2")
v2y <- c("column 1", "column 2", "column 1")
v2n <- c("column 2", "column 1", "column 2")
q <- c("q1",  "q2",  "q3")
#create reference dataframe, with character values
yn.dat <- data.frame(cbind(q, v1y, v1n, v2y, v2n), stringsAsFactors=FALSE)

> yn.dat
   q      v1y      v1n      v2y      v2n
1 q1 column 2 column 1 column 1 column 2
2 q2 column 2 column 1 column 2 column 1
3 q3 column 1 column 2 column 1 column 2

然后我创建了一个函数来通过数据框中的问题变量查找版本和索引。

#function for calculating yes/no
yn.code <- function(v1y, v1n, v2y, v2n, q){
ifelse(xdat$version==1 & xdat[,q]==v1y, "yes", ifelse(xdat$version==2 & xdat[,q]==v2y, "yes", ifelse(xdat$version==1 & xdat[,q]==v1n, "no", ifelse(xdat$version==2 & xdat[,q]==v2n, "no", NA))))    
}

当我 运行 函数时,它不会为所有响应生成正确的是和否值。

#result
yn.res <- yn.code(yn.dat$v1y, yn.dat$v1n, yn.dat$v2y, yn.dat$v2n, yn.dat$q)

    > yn.res 
     q1    q2    q3   
[1,] "yes" "yes" NA   
[2,] NA    "yes" "no" 
[3,] "yes" NA    "yes"
[4,] NA    NA    NA   
[5,] NA    "no"  "yes"

它似乎在错误的地方为 NA 编码而且它没有return输入正确的值。

起初我认为函数循环遍历 yn.dat 中的 q 所以它读取第四行数据并将 q1 的规则应用于第四个受访者的所有响应,并将 q2 的规则应用于所有响应第五位受访者,但这似乎与问题所在不符。

可能我需要在函数中包含一个 %in% 参数来查找 yn.dat 中的 xdat 变量名称,然后 return 我正在寻找的值?

抱歉,如果这是一个简单的编程问题,但我已经为此绞尽脑汁了一段时间,而且还是个新手。

我不能告诉你为什么你的代码不能正常工作。但是如此复杂地使用 ifelse() 似乎不是一个好主意。

一种可能的替代方法是创建一个查找 table。为此,您的数据框 yn.dat 需要转换为不同的格式。根据您实际创建的方式 yn.dat,从一开始就以该格式创建它可能更好,但我仍然可以向您展示如何从您当前的格式到达那里:

library(tidyr)
library(dplyr)
# convert to long format
yn.dat2 <- gather(yn.dat, type, answer, -q)
# split type up into version and yes/no
yn.dat2 <- mutate(yn.dat2, version = as.numeric(substr(type, 2, 2)),
                  yn = ifelse(substr(type, 3, 3) == "y", "yes", "no")) %>%
          select(-type)
yn.dat2
##     q   answer version  yn
## 1  q1 column 2       1 yes
## 2  q2 column 2       1 yes
## 3  q3 column 1       1 yes
## 4  q1 column 1       1  no
## 5  q2 column 1       1  no
## 6  q3 column 2       1  no
## 7  q1 column 1       2 yes
## 8  q2 column 2       2 yes
## 9  q3 column 1       2 yes
## 10 q1 column 2       2  no
## 11 q2 column 1       2  no
## 12 q3 column 2       2  no

问题(q)、列(answer)和version的每种可能组合都有一行数据,对应的值为"yes""no"。现在,我将定义每行唯一特征的列名称,这将使我能够稍后查找 table:

row.names(yn.dat2) <- paste(yn.dat2$q, yn.dat2$answer, yn.dat2$version,
                            sep = "-")

接下来,我定义了一个函数,该函数使用查找 table 将 xdat 的单个列(以其名称为特征)转换为 "yes""no":

do_one_q <- function(q) {
  keys <- paste(q, xdat[, q], xdat[, "version"], sep = "-")
  yn.dat2[keys, "yn"]
}

我根据 xdat 中的值创建了我们用于上述行名称的相同类型的键。然后该键用于子集 yn.dat2。并不是说这也适用于 "convert" xdat 中的 NAs 到 NAs:例如 q1 中的 NA 的键是 "q1-NA-2",如果您使用不存在的键进行索引,则返回 NA

yn.dat2["q1-NA-2", "yn"]
## [1] NA

因此不需要特殊处理缺失值。

最后一步是将此函数应用于所有问题,如下所示:

qs <- paste0("q", 1:3)
xdat_new <- as.data.frame(lapply(qs, do_one_q))
names(xdat_new) <- qs
xdat_new
##     q1   q2  q3
## 1  yes   no yes
## 2  yes  yes  no
## 3  yes  yes yes
## 4 <NA> <NA>  no
## 5   no   no yes

编辑:

转换为长格式也可以使用 melt() 而不是 gather() 来完成。只需将涉及 gather() 的行替换为

library(reshape2)
# convert to long format
yn.dat2 <- melt(yn.dat, id = "q", variable.name = "type", value.name = "answer")