我有一个宽格式的数据框,在不同的日期范围内重复测量.在我的例子中,有三个不同的时期,都有相应的值.例如,第一次测量(Value1)是在DateRange1StartDateRange1End年间测量的:

ID DateRange1Start DateRange1End Value1 DateRange2Start DateRange2End Value2 DateRange3Start DateRange3End Value3
1 1/1/90 3/1/90 4.4 4/5/91 6/7/91 6.2 5/5/95 6/6/96 3.3 

我希望将数据reshape 为长格式,以便将DateRangeXStart和DateRangeXEnd列分组,.因此,原来表格中的1行变成了新表格中的3行:

ID DateRangeStart DateRangeEnd Value
1 1/1/90 3/1/90 4.4
1 4/5/91 6/7/91 6.2
1 5/5/95 6/6/96 3.3

我知道一定有办法用reshape2/melt/recast/tidyr做到这一点,但我似乎不知道如何以这种特殊的方式将多组度量变量映射到单组值列中.

推荐答案

1.0.0版起,tidyr软件包的功能pivot_longer()就可以使用多个值/度量列从宽格式reshape 为长格式.

这比之前的tidyr策略gather()spread()(见@AndrewMacDonald的答案)要好,因为属性不再被删除(在下面的示例中,日期仍然是日期,数字仍然是数字).

library("tidyr")
library("magrittr")

a <- structure(list(ID = 1L, 
                    DateRange1Start = structure(7305, class = "Date"), 
                    DateRange1End = structure(7307, class = "Date"), 
                    Value1 = 4.4, 
                    DateRange2Start = structure(7793, class = "Date"),
                    DateRange2End = structure(7856, class = "Date"), 
                    Value2 = 6.2, 
                    DateRange3Start = structure(9255, class = "Date"), 
                    DateRange3End = structure(9653, class = "Date"), 
                    Value3 = 3.3),
               row.names = c(NA, -1L), class = c("tbl_df", "tbl", "data.frame"))

pivot_longer()(对应:pivot_wider())与gather()类似.

如果所有列名都遵循特定的模式,如Start_1End_1Start_2等,这是最简单的.

(names(a) <- sub("(\\d)(\\w*)", "\\2_\\1", names(a)))
#>  [1] "ID"               "DateRangeStart_1" "DateRangeEnd_1"  
#>  [4] "Value_1"          "DateRangeStart_2" "DateRangeEnd_2"  
#>  [7] "Value_2"          "DateRangeStart_3" "DateRangeEnd_3"  
#> [10] "Value_3"

pivot_longer(a, 
             cols = -ID, 
             names_to = c(".value", "group"),
             # names_prefix = "DateRange",
             names_sep = "_")
#> # A tibble: 3 x 5
#>      ID group DateRangeEnd DateRangeStart Value
#>   <int> <chr> <date>       <date>         <dbl>
#> 1     1 1     1990-01-03   1990-01-01       4.4
#> 2     1 2     1991-07-06   1991-05-04       6.2
#> 3     1 3     1996-06-06   1995-05-05       3.3

或者,可以使用提供更精细控制的pivot spec进行reshape (参见下面的链接):

spec <- a %>%
    build_longer_spec(cols = -ID) %>%
    dplyr::transmute(.name = .name,
                     group = readr::parse_number(name),
                     .value = stringr::str_extract(name, "Start|End|Value"))

pivot_longer(a, spec = spec)

reprex package(v0.2.1)于2019-03-26创建

另见:https://tidyr.tidyverse.org/articles/pivot.html

R相关问答推荐

将coord_sf与geom_spatraster一起使用会更改分辨率

替换字符的所有实例,但仅限于匹配字符串中

为什么stat_bin在R中的ggplot中显示错误的数字?

如何判断某列中由某些行组成的百分比

使用Shiny组合和显示复制和粘贴的数据

使用对管道内单元格的引用生成新变量

查找图下的面积

如何在xyplot中 for each 面板打印R^2

在R中,如何在每个堆叠的条上放置误差条,特别是当使用facet_grid时?

使用sf或terra的LINESTRAING的累积长度

对于变量的每个值,仅 Select 包含列表中所有值的值.R

将. xlsx内容显示为HTML表

展开对数比例绘图的轴(添加填充)

跨列查找多个时间报告

随机森林的带Shap值的蜂群图

如何在PDF格式的kableExtra表格中显示管道字符?

如何使用字符串从重复的模式中提取多个数字?

用满足特定列匹配的另一行替换NA行

根据排名的顶点属性调整曲线图布局(&Q)

从矩阵创建系数图