R-如何将多个案例(行)放在一行中

R- How to put multiple cases (rows) in one row

我正在用 R 编写一些代码,但遇到了一个问题。

我有一个数据集,参与者在不同的时间被问到相同的问题。有一个id变量,一个记录我们正在处理的实例的时间变量,以及一个结果变量。

我做了一些研究,发现 post 与我正在尝试做的类似。

我正在尝试做与 post 中所做的完全相反的事情。

我创建了这个小代码来了解我正在处理的内容。

A1
id       time  x
1000     1     1
1000     2     2
1000     3     3
1000     4     4
1001     1     1
1001     2     2
1001     3     3
1001     4     4

我需要做的是重新组织数据集,使每个案例都在一行上,并且我多次重复每个 X 变量(x1 将是第一个时间点,x2 将是第二个时间点,等等) .这是我希望最终数据框看起来像的示例代码。

B1
id     x1     x2     x3     x4
1000    1     2      3      4
1001    1     2      3      4

我的代码中有一些细微差别使这种情况变得非常棘手。一些参与者比其他参与者拥有更多的 x 条目(一些参与者只有 1 或 2 个不同的 x 值,而其他参与者有 7 或 8 个)。还有一些数据缺失。

我已经通过几种方法解决了这个问题,但没有成功。我不确定处理这种情况的最佳方法是什么。我尝试过的尝试要么需要大量代码,通常是相同的基本代码重复多次,要么代码不起作用。这是我尝试过的。

我尝试使用 for 循环。我尝试创建一个新变量来通过 id 识别参与者,然后识别他们第一次进行调查的时间,然后我使用第一个 x 值。然后我会为每个时间点重复这个(对于时间 2-找到给定参与者的第二个 x 值,对于时间 3-找到给定参与者的第三个 x 值,等等)。因为我目前有 1 到 10 个时间点,所以这涉及很多 for 循环。因为有的人没有第6次、第7次,代码往往没有运行。这是我尝试过的 for 循环的示例。

for (i in A1$id) {
  temp.txt<- paste (
    c ("A1$x1 [A$id ==", i," & A$time == 1] <- A1$x"
    ),   collapse = "")
  eval (parse(text = temp.txt))
}

我尝试对每个时间点的数据进行子集化,然后在最后将数据合并在一起。如果我尝试这样做,我会丢失数据,而且我还会遇到变量名称不再被接受的问题(我认为因为名称相似,R 在重命名所有内容方面存在问题)。这是该代码的示例。

t1 <- subset (A1, A$time == 1)
t2 <- subset (A1, A$time == 2)
t3 <- subset (A1, A$time == 3)
t4 <- subset (A1, A$time == 4)

Z1 <- merge (t1, t2, by = "id")
Z2 <- merge (Z1, t3, by = "id")
Z3 <- merge (Z2, t4, by = "id")

是否有 different/easier 方法来解决这个问题?谢谢,非常感谢。

1) reshape 这称为将长格式转换为宽格式。在 base R 中,我们可以使用 reshape 给出以下数据框。请注意,reshape 假设如果有名为 idtime 的列,那么这些列就是 id 和 time 列,但如果它们被命名为其他名称,我们将不得不使用适当的 reshape 个参数。

reshape(DF, dir = "wide")
##     id x.1 x.2 x.3 x.4
## 1 1000   1   2   3   4
## 5 1001   1   2   3   4

2) xtabs 另一个基本的 R 解决方案是使用 xtabs,它给出以下 table 对象:

xtabs(x ~ ., DF)
##       time
## id     1 2 3 4
##   1000 1 2 3 4
##   1001 1 2 3 4

3) tapplytapply 这给出了这个矩阵:

with(DF, tapply(x, list(id, time), c))
##      1 2 3 4
## 1000 1 2 3 4
## 1001 1 2 3 4

4) pivot wider tidyr 包 pivot_wider 可以做到这一点:

library(tidyr)

pivot_wider(DF, names_from = "time", values_from = x)
## # A tibble: 2 x 5
##      id   `1`   `2`   `3`   `4`
##   <int> <int> <int> <int> <int>
## 1  1000     1     2     3     4
## 2  1001     1     2     3     4

备注

可重现形式的输入:

Lines <- "id       time  x
1000     1     1
1000     2     2
1000     3     3
1000     4     4
1001     1     1
1001     2     2
1001     3     3
1001     4     4"
DF <- read.table(text = Lines, header = TRUE)

使用data.table你可以试试

library(data.table)
setDT(A1) #Converting into data.table
result <- dcast(A1, id~x, value.var= "time") #long to wide conversion
names(result)[-1]<- paste0("x.",names(result)[-1]) #setting the names accordingly
result #your result

     id x.1 x.2 x.3 x.4
1: 1000   1   2   3   4
2: 1001   1   2   3   4