【问题标题】:gather / melt wide data into different value columns [duplicate]将宽数据收集/融合到不同的值列中[重复]
【发布时间】:2016-05-15 02:33:40
【问题描述】:

我有一个宽格式的数据,其中有 两组不同的值列:那些包含质量(Mass1、Mass2 等)和那些包含相应日期的那些(Mass1_date、Mass2_date 等) .

library(tidyr)
library(dplyr)
library(lubridate)

df <- structure(list(Year = 2004, Nest_no = 21, Mass1 = 2325, Mass1_date = structure(1081987200, class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), Mass2 = 2000, Mass2_date = structure(1082851200, class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), Mass3 = 1750, Mass3_date = structure(1083715200, class = c("POSIXct", 
"POSIXt"), tzone = "UTC")), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -1L), .Names = c("Year", "Nest_no", "Mass1", 
"Mass1_date", "Mass2", "Mass2_date", "Mass3", "Mass3_date"))

df

## Source: local data frame [1 x 8]
## 
##    Year Nest_no Mass1 Mass1_date Mass2 Mass2_date Mass3 Mass3_date
##   (dbl)   (dbl) (dbl)     (time) (dbl)     (time) (dbl)     (time)
## 1  2004      21  2325 2004-04-15  2000 2004-04-25  1750 2004-05-05

我想将数据“整理”成长格式,其中两组值列被gathered (melted) 分成两个不同的值列,一列包含“质量列”的值,一个包含“日期列”的值:

## Source: local data frame [3 x 5]
## 
##    Year Nest_no capture       date weight
##   (dbl)   (dbl)   (dbl)     (date)  (dbl)
## 1  2004      21       1 2004-04-15   2325
## 2  2004      21       2 2004-04-25   2000
## 3  2004      21       3 2004-05-05   1750

起初,我以为我可以使用tidyr 并分两步完成。

gather(df, capture, date, contains("Date")) %>% 
  gather(capture2, weight, contains("Mass"))

## Source: local data frame [9 x 6]
## 
##    Year Nest_no    capture       date capture2 weight
##   (dbl)   (dbl)      (chr)     (time)    (chr)  (dbl)
## 1  2004      21 Mass1_date 2004-04-15    Mass1   2325
## 2  2004      21 Mass2_date 2004-04-25    Mass1   2325
## 3  2004      21 Mass3_date 2004-05-05    Mass1   2325
## 4  2004      21 Mass1_date 2004-04-15    Mass2   2000
## 5  2004      21 Mass2_date 2004-04-25    Mass2   2000
## 6  2004      21 Mass3_date 2004-05-05    Mass2   2000
## 7  2004      21 Mass1_date 2004-04-15    Mass3   1750
## 8  2004      21 Mass2_date 2004-04-25    Mass3   1750
## 9  2004      21 Mass3_date 2004-05-05    Mass3   1750

但是,它没有按预期工作。经过几次尝试,我上来了 使用此解决方案:

df <- gather(df, capture2, weight, contains("Mass"), convert = T) %>% 
  mutate(capture = extract_numeric(capture2))

## Warning: attributes are not identical across measure variables; they will
## be dropped

df$capture2 <- ifelse(grepl("date", df$capture2), "date", "weight")

df <- spread(df, capture2, weight) %>% 
  mutate(date = as.Date(as.POSIXct(date, origin = "1970-01-01")))

df

## Source: local data frame [3 x 5]
## 
##    Year Nest_no capture       date weight
##   (dbl)   (dbl)   (dbl)     (date)  (dbl)
## 1  2004      21       1 2004-04-15   2325
## 2  2004      21       2 2004-04-25   2000
## 3  2004      21       3 2004-05-05   1750

我想知道是否有更好的方法来实现这一目标?

谢谢你,菲利普

【问题讨论】:

    标签: r reshape tidyr


    【解决方案1】:

    我们可以使用来自data.tablemelt 轻松完成此操作。 measure 可以采用多个列名patterns 并将“宽”格式转换为“长”格式。

    library(data.table)
    melt(as.data.table(df), measure=patterns('\\d$', 'date$'),
             variable.name='capture', value.name= c('weight', 'date'))
    #   Year Nest_no capture weight       date
    #1: 2004      21       1   2325 2004-04-15
    #2: 2004      21       2   2000 2004-04-25
    #3: 2004      21       3   1750 2004-05-05
    

    【讨论】:

    • 谢谢,你的回答很完美。
    猜你喜欢
    • 2018-01-03
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 2011-12-15
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-11
    相关资源
    最近更新 更多