如何将一个具有“四重嵌套”的多级结构的宽数据框转换为长数据框?

8
我进行了一项研究,回顾起来(人生经验教训:-))似乎生成了多层数据。现在我正在尝试将数据集从宽格式重构为长格式,以便使用例如lme4进行分析。
在这样做的过程中,我遇到了一个问题,这个问题我之前遇到过几次,但我从未找到好的解决方案。这次我再次搜索,但我可能使用了错误的关键字,或者这个问题比我想象的要罕见得多。
基本上,在这个数据集中,变量名称指示收集哪些测量数据。我要求参与者对干预措施(可以是任何事情)进行评分。每种干预措施都属于6个行为领域之一。此外,参与者对每种干预措施进行评分,无论是单独呈现还是与另一种干预措施同时呈现,或者与两种其他干预措施同时呈现。有三种类型的干预措施,它们都在我向他们提供一些信息之前(t0)和之后(t1)进行了评估。
因此,实际上,我有一个可以像这样重新生成的数据框:
### Elements of the variable names
measurementMomentsVector <- c("t0", "t1");
interventionTypesVector <- c("fear", "know", "scd");
nrOfInterventionsSimultaneouslyVector <- c(1, 2, 3);
behaviorDomainsVector <- c("diet", "pox", "alc", "smoking", "traff", "adh");

### Generate a vector with all variable names
variableNames <-
  apply(expand.grid(measurementMomentsVector,
                    interventionTypesVector,
                    nrOfInterventionsSimultaneouslyVector,
                    behaviorDomainsVector),
        1, paste0, collapse="_");

### Generate 5 'participants' worth of data
wideData <- data.frame(matrix(rnorm(5*length(variableNames)), nrow=5));

### Assign names
names(wideData) <- variableNames;

### Add unique id variable for every participants
wideData$id <- 1:5;

因此,使用 head(wideData)[, 1:5] 您可以大致了解数据框的外观:

  t0_fear_1_diet t1_fear_1_diet t0_know_1_diet t1_know_1_diet t0_scd_1_diet
1     -0.9338191      0.9747453      1.0069036      0.3500103  -0.844699708
2      0.8921867      1.3687834     -1.2005791      0.2747955   1.316768219
3      1.6200200      0.5245470     -1.2910586      1.3211912  -0.174795144
4      0.1543738      0.7535642      0.4726131     -0.3464789  -0.009190702
5     -1.3676692     -0.4491574     -2.0902003     -0.3484678  -2.537501824

现在,我想将这些数据转换为长数据框,包含6个变量,例如'id'、'measurementMoment'、'interventionType'、'nrOfInterventionsSimultaneously'、'behaviorDomain'和'evaluation',其中第一个变量表示记录所属的参与者,最后一个变量是参与者给定特定干预的得分(评分、等级、评估),中间的四个变量指示正在评估哪种干预措施。
我可能可以为此问题编写一些“自定义”代码,但我希望R“有解决方案”。我一直在尝试使用reshape2,例如:
longData <- reshape(wideData, varying=1:(ncol(wideData)-1),
                    idvar="id",
                    sep="_", direction="long")

但是它无法猜测时间变化的变量:

Error in guess(varying) : 
  failed to guess time-varying variables from their names

我已经多次遇到这个问题,但在网上找不到任何答案。现在我真的需要继续前进,所以在求助定制方案之前,我想尝试一下最后的努力:-)

如果有人能提供任何指针,我将非常感激!!!


firstSecondOccurrenceVector 的值是多少? - krlmlr
抱歉,那是之前我还没有澄清的遗留问题!现在它已经不重要了 :-) 对于造成的混淆,非常抱歉! - Matherion
不要道歉,相反地,编辑代码使其运行。 - IRTFM
那时候我已经完成了。 - Matherion
1个回答

10

我认为你的问题可以通过以下两个步骤来解决:

  1. 将您的数据融合成一个长的 data.frame (或者像我一样,在一个长的 data.table 中)
  2. 将包含所有标签的 variable 列拆分为每个所需组变量的单独列。

由于这些信息都在标签中,因此可以使用 data.table 包中的 tstrsplit 函数轻松实现此目标。

这就是你可能正在寻找的内容:

library(data.table)
longData <- melt(setDT(wideData), id.vars="id")
longData[, c("moment", "intervention", "number", "behavior") := 
                tstrsplit(variable, "_", type.convert = TRUE)
       ][, variable:=NULL]

结果:

> head(longData,15)
    id       value moment intervention number behavior
 1:  1 -0.07747254     t0         fear      1     diet
 2:  2 -0.76207379     t0         fear      1     diet
 3:  3  1.15501244     t0         fear      1     diet
 4:  4  1.24792369     t0         fear      1     diet
 5:  5 -0.28226121     t0         fear      1     diet
 6:  1 -1.04875354     t1         fear      1     diet
 7:  2 -0.91436882     t1         fear      1     diet
 8:  3  0.72863487     t1         fear      1     diet
 9:  4  0.10934261     t1         fear      1     diet
10:  5 -0.06093002     t1         fear      1     diet
11:  1 -0.70725760     t0         know      1     diet
12:  2  1.06309003     t0         know      1     diet
13:  3  0.89501164     t0         know      1     diet
14:  4  1.48148316     t0         know      1     diet
15:  5  0.22086835     t0         know      1     diet
作为 data.table 的替代方案,您还可以使用 splitstackshape 包的 cSplit 函数来拆分 variable 列(然后您将不得不重新命名生成的变量列):
作为 data.table 的另一种选择,您可以使用 splitstackshape 包的 cSplit 函数来拆分 variable 列(但您需要事后重命名生成的变量列)。
library(splitstackshape)
longData <- cSplit(longData, sep="_", "variable", "wide", type.convert=TRUE)
names(longData) <- c("id","value","moment","intervention","number","behavior")

或使用 tidyr

library(tidyr)
separate(longData, variable, c("moment", "intervention", "number", "behavior"), sep="_", remove=TRUE)

太好了,谢谢!正是我需要的。还要感谢您向我指出data.table,它看起来很棒!非常感谢!!! - Matherion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接