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
假设如果有名为 id
和 time
的列,那么这些列就是 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) tapply 或 tapply
这给出了这个矩阵:
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
我正在用 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
假设如果有名为 id
和 time
的列,那么这些列就是 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) tapply 或 tapply
这给出了这个矩阵:
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