(已编辑)我有一个很长的数据集,其中包含多列长格式。以下是数据示例:
Groups duration response value trial
------ ----- -------- --------- --------
C 525 ID 5578 ID
C 525 1-1 676|342 C3
C 525 1-2 676|342 C3
C 525 1-3 676|342 C3
C 525 1-4 676|342 C3
C 525 1-5 676|342 C3
C 521 ID 6331 ID
C 521 1-1 643|461 C3
在此数据框中,每个参与者的 ID 与响应和值位于同一列。我需要的是将对应于“ID”的行放入一个单独的重复测量列中,使其看起来像这样:
Groups duration ID response value trial
------ ----- ------ -------- --------- --------
C 525 5578 1-1 676|342 C3
C 525 5578 1-2 676|342 C3
C 525 5578 1-3 676|342 C3
C 525 5578 1-4 676|342 C3
C 525 5578 1-5 676|342 C3
C 525 5578 1-6 676|342 C3
C 521 6331 1-1 643|461 C3
C 521 6331 1-2 643|461 C3
C 521 6331 1-3 643|461 C3
C 521 6331 1-4 643|461 C3
C 521 6331 1-5 643|461 C3
C 521 6331 1-6 643|461 C3
我最初的尝试是将数据框转换为宽格式,以便 ID 和其他响应各有自己的列,然后再次将其设为长,但仅适用于示例中的 1-1 到 1-6 列,使用此代码:
df <- spread(df, response, value)
#fill in the whole column with corresponding values
df<-fill(df, ID, .direction="down")
df <- gather(df, name, coordinates, 9:1417, factor_key=TRUE)
第一部分有效。我得到一个带有 ID 列的数据框。但是,当我尝试将其他列转换回长格式时,出现错误:“错误:向量内存已耗尽(达到限制?)”
我想这是因为列太多了,我的记忆力受不了。 有没有更简单的方法来做到这一点?
答案 0 :(得分:1)
一个选项是通过执行逻辑向量 (response == 'ID'
) 的累积和来基于 'ID' 的出现创建一个分组,然后创建 'ID' 列作为 first
中的元素'value',然后用 slice
删除第一行并删除 'grp' 列
library(dplyr)
df %>%
group_by(grp = cumsum(response == 'ID'), Groups) %>%
mutate(ID = first(value)) %>%
slice(-1) %>%
ungroup %>%
select(-grp)
-输出
# A tibble: 6 x 6
# Groups duration response value trial ID
# <chr> <int> <chr> <chr> <chr> <chr>
#1 C 525 1-1 676|342 C3 5578
#2 C 525 1-2 676|342 C3 5578
#3 C 525 1-3 676|342 C3 5578
#4 C 525 1-4 676|342 C3 5578
#5 C 525 1-5 676|342 C3 5578
#6 C 521 1-1 643|461 C3 6331
如果我们需要通过将“响应”从“1-1”变为“1-6”来扩展行
library(stringr)
library(tidyr)
df %>%
group_by(grp = cumsum(response == 'ID'), Groups) %>%
mutate(ID = first(value)) %>%
slice(-1) %>%
group_by(Groups, duration, value, trial, ID, .add = TRUE) %>%
complete(response = str_c('1-', 1:6)) %>%
ungroup %>%
select(-grp)
-输出
# A tibble: 12 x 6
# Groups duration value trial ID response
# <chr> <int> <chr> <chr> <chr> <chr>
# 1 C 525 676|342 C3 5578 1-1
# 2 C 525 676|342 C3 5578 1-2
# 3 C 525 676|342 C3 5578 1-3
# 4 C 525 676|342 C3 5578 1-4
# 5 C 525 676|342 C3 5578 1-5
# 6 C 525 676|342 C3 5578 1-6
# 7 C 521 643|461 C3 6331 1-1
# 8 C 521 643|461 C3 6331 1-2
# 9 C 521 643|461 C3 6331 1-3
#10 C 521 643|461 C3 6331 1-4
#11 C 521 643|461 C3 6331 1-5
#12 C 521 643|461 C3 6331 1-6
优点是我们不需要做任何整形,而是在相同的数据上创建列并在末尾删除一些行
df <- structure(list(Groups = c("C", "C", "C", "C", "C", "C", "C",
"C"), duration = c(525L, 525L, 525L, 525L, 525L, 525L, 521L,
521L), response = c("ID", "1-1", "1-2", "1-3", "1-4", "1-5",
"ID", "1-1"), value = c("5578", "676|342", "676|342", "676|342",
"676|342", "676|342", "6331", "643|461"), trial = c("ID", "C3",
"C3", "C3", "C3", "C3", "ID", "C3")), class = "data.frame",
row.names = c(NA,
-8L))
答案 1 :(得分:0)
使用 ID
创建一个新列 (value
) 并使用 replace
NA
创建一个新列 (response != 'ID'
,fill
NA
} 值并删除带有 response = 'ID'
的行。
library(dplyr)
library(tidyr)
df %>%
mutate(ID = replace(value, response != 'ID', NA)) %>%
fill(ID) %>%
filter(response != 'ID')
# Groups duration response value trial ID
#1 C 525 1-1 676|342 C3 5578
#2 C 525 1-2 676|342 C3 5578
#3 C 525 1-3 676|342 C3 5578
#4 C 525 1-4 676|342 C3 5578
#5 C 525 1-5 676|342 C3 5578
#6 C 521 1-1 643|461 C3 6331
答案 2 :(得分:0)
基本的 R 方法可能是在 cumsum 上拆分,然后重新组合(并重新排列列以获得预期输出):
df <- split(df, cumsum(df$response =="ID"))
do.call(rbind, lapply(df, function(x) {
y=x[-1,]; y$ID <- x$value[1]; y[, c(1:2,6,3:5)]}))