微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

重塑数据:提取“一些”行并将它们转换为 R 中的新列 数据

如何解决重塑数据:提取“一些”行并将它们转换为 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 举报,一经查实,本站将立刻删除。