我正在编写一个输出.csv文件的调查。在这个csv中,我有一些空格分隔的条目,它们代表多选问题(例如,具有多个响应的问题)。最后,我想将这些空格分隔的条目解析为它们自己的列,并为它们创建标题,以便我知道它们来自哪里。
例如,我可以从这开始(注意多选列后面有一个_M):
Q1, Q2_M, Q3, Q4_M
6, 1 2 88, 3, 3 5 99
6, , 3, 1 2
我想谈谈这个:
Q1, Q2_M_1, Q2_M_2, Q2_M_88, Q3, Q4_M_1, Q4_M_2, Q4_M_3, Q4_M_5, Q4_M_99
6, 1, 1, 1, 3, 0, 0, 1, 1, 1
6,,,,3,1,1,0,0,0
我认为这是一个相对常见的问题需要处理,但我无法在R部分找到它。有什么想法在导入.csv后如何在R中执行此操作?我的一般想法(通常导致程序效率低下)是我可以: (1)用grep()拉出具有特殊后缀的列号 (2)循环(或使用apply)这些列中的每个条目并确定响应级别,然后相应地创建列 (3)循环(或使用apply)并在适当的列中放置指示符以指示选择的存在
我感谢任何帮助,如果不清楚,请告诉我。
答案 0 :(得分:2)
我同意ran2和aL3Xa,您可能希望更改数据格式,以便为每个可能的响应提供不同的列。但是,如果您将数据集更改为更好的格式证明存在问题,则可以按照您的要求进行操作。
process_multichoice <- function(x) lapply(strsplit(x, " "), as.numeric)
q2 <- c("1 2 3 NA 4", "2 5")
processed_q2 <- process_multichoice(q2)
[[1]]
[1] 1 2 3 NA 4
[[2]]
[1] 2 5
建议使用不同响应的不同列的原因是因为尝试从此表单中的数据中检索任何统计信息仍然非常不愉快。虽然你可以做像
这样的事情# Number of reponses given
sapply(processed_q2, length)
#Frequency of each response
table(unlist(processed_q2), useNA = "ifany")
编辑:还有一条建议。将处理数据的代码与分析它的代码分开。如果您创建任何图形,请将用于创建它们的代码再次分开。我一直在把事情混合在一起,而且它并不漂亮。 (特别是六个月后你回到代码时。)
答案 1 :(得分:1)
我不完全确定你要分别做什么,你的原因是这样的编码。因此,我的建议更为一般 - 所以只是想澄清一下,我会尝试做出更具体的回应。
1)我说你自己编写调查代码,这很好,因为这意味着你对你的.csv文件有影响力。我永远不会在同一个.csv文件中使用不同类型的分隔。就像你在第二个区块中建议的那样,从一开始就做命名。 否则,您可能会遇到问题,例如复选框。假设有人检查5个可能答案中的3个,下一个只检查1(即“不知道”)。现在,创建一个电子表格(data.frame)类型的结果视图要比创建一个只需要重新编码的空字段(结果是R中的NA)要困难得多。
2)另一个重要的问题是你是否打算进行小组调查(即纵向研究一遍又一遍地询问同一个参与者)。这(以及其他许多)是考虑将数据保存到MySQL数据库而不是.csv的一个很好的理由。 RMySQL可以直接连接到数据库并访问其表,更重要的是它的VIEWS。 视图确实有助于调查数据,因为您可以根据许多不同的需求重新排列不同视图中的数据。
3)除了所有的个人/意见和经验,这里有一些(较少有偏见的)文学入门: Complex Surveys: A Guide to Analysis Using R (Wiley Series in Survey Methodology
这本书相对简单,省略了小组调查,但提供了很多R代码和实例应该是一个实际的开始。
为了防止重新发明轮子,您可能需要检查LimeSurvey,这是一个非常体面的(不是说模板:))工具,用于调查导体。除此之外,TYPO3 CMS扩展程序pbsurvey和ke_questionnaire(应该)也运行良好(仅经过测试的pbsurvey)。
答案 2 :(得分:1)
多项选择项应始终编码为单独的变量。也就是说,如果您有5个选项和多个选项,则应将它们编码为 i1,i2,i3,i4,i5 ,即每个都是二进制变量(0-1)。我看到第一个示例中的 Q4_M 变量的值为3 5 99
。这是否意味着您在一个项目中有99个替代品?哎哟...
首先,您应该继续为多项选项中的每个替代项创建单独的变量。那就是:
# note that I follow your example with Q4_M variable
dtf_ins <- as.data.frame(matrix(0, nrow = nrow(<initial dataframe>), ncol = 99))
# name vars appropriately
names(dtf_ins) <- paste("Q4_M_", 1:99, sep = "")
现在你有一个带有0的data.frame,所以你需要做的是在适当的位置得到1(这有点麻烦),一个函数将完成这项工作......
# first you gotta change spaces to commas and convert character variable to a numeric one
y <- paste("c(", gsub(" ", ", ", x), ")", sep = "")
z <- eval(parse(text = y))
# now you assing 1 according to indexes in z variable
dtf_ins[1, z] <- 1
这就是它......基本上,您想重新考虑使用 _M 变量创建data.frame,这样您就可以编写一个自动执行此插入的函数。避免for
循环!
或者更好的是,创建一个包含逻辑的矩阵,只需dtf[m] <- 1
,其中 dtf 是您的多项选择data.frame, m 是具有逻辑的矩阵。
我想在这个问题上给你更多帮助,但是我在一个宽夜之后恢复健康! =)希望我帮了一下! =)
答案 3 :(得分:0)
感谢所有回复。我同意大多数人的看法,这种格式有点傻,但这是我必须要处理的(调查是编码并在下周开始使用)。这是我从所有回复中得出的结论。我确信这不是最优雅或最有效的方法,但我认为它应该有用。
colnums <- grep("_M",colnames(dat))
responses <- nrow(dat)
for (i in colnums) {
vec <- as.vector(dat[,i]) #turn into vector
b <- lapply(strsplit(vec," "),as.numeric) #split up and turn into numeric
c <- sort(unique(unlist(b))) #which values were used
newcolnames <- paste(colnames(dat[i]),"_",c,sep="") #column names
e <- matrix(nrow=responses,ncol=length(c)) #create new matrix for indicators
colnames(e) <- newcolnames
#next loop looks for responses and puts indicators in the correct places
for (i in 1:responses) {
e[i,] <- ifelse(c %in% b[[i]],1,0)
}
dat <- cbind(dat,e)
}
欢迎提出改进建议。