R中没有For循环的数据帧匹配和分解

时间:2014-06-24 18:55:50

标签: arrays r for-loop

我有两个数据框,一个是调查响应选项(级别),另一个是编码响应。在数据框架中,列具有相同的名称,但不一定是相同的顺序。此外,在级别数据框架内,问题可能有不同数量的响应选项。

levels <- data.frame(restaurant=c("TACO BELL","CHIPOTLE",""),
                     would_recommend=c("YES","NO",""),
                     satisfaction=c("VERY SATISFIED","SATISFIED","UNSATISFIED"))                  

responses <- data.frame(satisfaction=c(2,2,1,1,3,3,2,2),
                        would_recommend=c(1,2,1,1,2,2,2,1),
                        restaurant=c(1,2,1,2,1,2,1,2))

响应本质上是其级别在级别表中具有相同名称列的因子,因此我想将它们转换为因子。

我知道我可以通过以下方式做到这一点:

for (i in 1:length(responses)){
  resp_levels <- levels[,match(names(responses)[i],names(levels))]
  responses[,i]<-factor(x=resp_levels[responses[,i]],levels=resp_levels)
}

如果没有For循环,是否有一种聪明的方法可以做到这一点?

1 个答案:

答案 0 :(得分:1)

我普遍同意@gogolews认为for循环没有任何问题,如果它适合你,尤其是像你这样的简单循环。但是,如果您真的需要非循环解决方案,则可以使用包tidyrdplyr的解决方案。对于一个非常庞大的数据集,这可能会更快,但很难肯定地说:

library(dplyr)
library(tidyr)

首先,将响应收集到长格式data.frame中,并添加一个id变量,以便我们知道以后哪些一起使用。我们将因子转换为字符,以便我们可以稍后按名称对其进行索引

new_responses <- responses %>% mutate(id = row_number(restaurant)) %>% 
gather(question,  response, -id) %>% mutate(question = as.character(question)) 

现在使用dplyr从级别data.frame中获取适当的级别,然后使用tidyr将其传回简短形式并删除不再需要的id。

responses2 <- new_responses %>% rowwise %>% 
mutate(response = as.character(levels[response, question])) %>% 
spread(question, response) %>% select(-id)
responses2

Source: local data frame [8 x 3]

  restaurant   satisfaction would_recommend
1  TACO BELL      SATISFIED             YES
2  TACO BELL VERY SATISFIED             YES
3  TACO BELL    UNSATISFIED              NO
4  TACO BELL      SATISFIED              NO
5   CHIPOTLE      SATISFIED              NO
6   CHIPOTLE VERY SATISFIED             YES
7   CHIPOTLE    UNSATISFIED              NO
8   CHIPOTLE      SATISFIED             YES

请注意,行不一定与原始行的顺序相同,但可以通过使用id变量来获取新的data.frame。