如何解决重塑数据:提取“一些”行并将它们转换为 R 中的新列 数据
(已编辑)我有一个很长的数据集,其中包含多列长格式。以下是数据示例:
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 列的数据框。但是,当我尝试将其他列转换回长格式时,出现错误:“错误:向量内存已耗尽(达到限制?)”
我想这是因为列太多了,我的记忆力受不了。 有没有更简单的方法来做到这一点?
解决方法
一个选项是通过执行逻辑向量 (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"),duration = c(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","6331","643|461"),trial = c("ID","C3","C3")),class = "data.frame",row.names = c(NA,-8L))
,
使用 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
,
基本的 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)]}))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。