有没有一种方法可以在数据框中绑定不同数量的行?
Is there a method to bind varying numbers of rows inside a dataframe?
我有一个大型数据框,其中包含 3 列,分别命名为 ID
、x
和 y
。有一些 "ID" 出现不止一次(可以是任意次数),通常 "x" 和 "y" 的值是不同的,只是 "y" 可以是NA
超过一个重复的 "ID"。我的目标是获得一个数据框,其中每个 ID 只出现一次,但可能重复项的 x 和 y 值是额外的新列。这是一个简单的例子:
ID x y
a 1 NA
b 2 6
a 3 7
b 4 NA
b 5 NA
这个 table 应该变成以下形式:
ID x1 y1 x2 y2 x3 y3
a 1 NA 3 7 NA NA
b 2 6 4 NA 5 NA
附加列的顺序无关紧要,只要 x 和 y 对仍然可识别即可。
我最大的问题是我需要将它应用于具有数千个不同 ID 的数据框,但到目前为止我找不到或无法编写可以自动执行此操作的函数。
到目前为止,最接近我的目标的是使用 unlist()
。例如。只查看带有 ID = "a"
的行并将它们分配给新的数据框 A,我可以使用
unlist( append(distinct(A, ID), unlist(select(A, x, y))) )
但我无法将其更普遍地应用于整个数据框。
我也研究了一些将特定行连接或合并在一起的方法,但我无法解决所需附加列数量不同的问题。
谢谢!!
这正在重塑您的数据。您需要一个 time
变量。我们可以将 ave 函数与行中的序列一起使用。 (我使用了 x,您可以使用任何非因子变量或简单地使用 1:nrow(df))。然后我们 reshape 到 wide
在基础 R 中你可以这样做:
reshape(transform(df,time=ave(x,ID,FUN=seq_along)),idvar = "ID",dir="wide",sep="")
ID x1 y1 x2 y2 x3 y3
1 a 1 NA 3 7 NA NA
2 b 2 6 4 NA 5 NA
由于data.table
dcast
需要多个value.var
,所以可以用dcast
来完成
library(data.table)
dcast(setDT(df1), ID ~ rowid(ID), value.var = c("x", "y"), sep="")
# ID x1 x2 x3 y1 y2 y3
#1: a 1 3 NA NA 7 NA
#2: b 2 4 5 6 NA NA
在tidyverse
中,这可以用pivot_wider
来完成(来自tidyr
的开发版本)
library(tidyverse)
df1 %>%
group_by(ID) %>%
mutate(rn = row_number()) %>%
pivot_wider(names_from = rn, values_from = c(x, y))
# A tibble: 2 x 7
# ID x_1 x_2 x_3 y_1 y_2 y_3
# <chr> <int> <int> <int> <int> <int> <int>
#1 a 1 3 NA NA 7 NA
#2 b 2 4 5 6 NA NA
数据
df1 <- structure(list(ID = c("a", "b", "a", "b", "b"), x = 1:5, y = c(NA,
6L, 7L, NA, NA)), class = "data.frame", row.names = c(NA, -5L
))
我有一个大型数据框,其中包含 3 列,分别命名为 ID
、x
和 y
。有一些 "ID" 出现不止一次(可以是任意次数),通常 "x" 和 "y" 的值是不同的,只是 "y" 可以是NA
超过一个重复的 "ID"。我的目标是获得一个数据框,其中每个 ID 只出现一次,但可能重复项的 x 和 y 值是额外的新列。这是一个简单的例子:
ID x y
a 1 NA
b 2 6
a 3 7
b 4 NA
b 5 NA
这个 table 应该变成以下形式:
ID x1 y1 x2 y2 x3 y3
a 1 NA 3 7 NA NA
b 2 6 4 NA 5 NA
附加列的顺序无关紧要,只要 x 和 y 对仍然可识别即可。
我最大的问题是我需要将它应用于具有数千个不同 ID 的数据框,但到目前为止我找不到或无法编写可以自动执行此操作的函数。
到目前为止,最接近我的目标的是使用 unlist()
。例如。只查看带有 ID = "a"
的行并将它们分配给新的数据框 A,我可以使用
unlist( append(distinct(A, ID), unlist(select(A, x, y))) )
但我无法将其更普遍地应用于整个数据框。
我也研究了一些将特定行连接或合并在一起的方法,但我无法解决所需附加列数量不同的问题。
谢谢!!
这正在重塑您的数据。您需要一个 time
变量。我们可以将 ave 函数与行中的序列一起使用。 (我使用了 x,您可以使用任何非因子变量或简单地使用 1:nrow(df))。然后我们 reshape 到 wide
在基础 R 中你可以这样做:
reshape(transform(df,time=ave(x,ID,FUN=seq_along)),idvar = "ID",dir="wide",sep="")
ID x1 y1 x2 y2 x3 y3
1 a 1 NA 3 7 NA NA
2 b 2 6 4 NA 5 NA
由于data.table
dcast
需要多个value.var
,所以可以用dcast
library(data.table)
dcast(setDT(df1), ID ~ rowid(ID), value.var = c("x", "y"), sep="")
# ID x1 x2 x3 y1 y2 y3
#1: a 1 3 NA NA 7 NA
#2: b 2 4 5 6 NA NA
在tidyverse
中,这可以用pivot_wider
来完成(来自tidyr
的开发版本)
library(tidyverse)
df1 %>%
group_by(ID) %>%
mutate(rn = row_number()) %>%
pivot_wider(names_from = rn, values_from = c(x, y))
# A tibble: 2 x 7
# ID x_1 x_2 x_3 y_1 y_2 y_3
# <chr> <int> <int> <int> <int> <int> <int>
#1 a 1 3 NA NA 7 NA
#2 b 2 4 5 6 NA NA
数据
df1 <- structure(list(ID = c("a", "b", "a", "b", "b"), x = 1:5, y = c(NA,
6L, 7L, NA, NA)), class = "data.frame", row.names = c(NA, -5L
))