使用tidyr

时间:2015-09-23 06:43:37

标签: r reshape tidyr

我有一个数据集,其中包含多个具有日期和相应值的列(重复测量)。有没有办法将其转换为包含(其他和仅)两列的长数据集 - 一个用于日期,一个用于 - 使用tidyr

以下代码生成示例数据框:

df <- data.frame(
   id = 1:10,
   age = sample(100, 10),
   date1 = as.Date('2015-09-22') - sample(100, 10),
   value1 = sample(100, 10),
   date2 = as.Date('2015-09-22') - sample(100, 10),
   value2 = sample(100, 10),
   date3 = as.Date('2015-09-22') - sample(100, 10),
   value3 = sample(100, 10))

输入表可能(11.8x10^138的概率)如下所示:

   id age      date1 value1      date2 value2      date3 value3
1   1  32 2015-08-01     37 2015-07-15     38 2015-09-09     81
2   2  33 2015-07-22     16 2015-06-26      1 2015-09-12     58
...
10 10  64 2015-07-23     78 2015-08-25     70 2015-08-05     90

我最终想要的是:

   id age       date  value
1   1  32 2015-08-01     37
2   1  32 2015-07-15     38
3   1  32 2015-09-09     81
4   2  33 2015-07-22     16
5   2  33 2015-06-26      1
...
30 10  64 2015-08-05     90

非常感谢tidyrreshape中提供的任何帮助。

5 个答案:

答案 0 :(得分:3)

应该有一些有效的方法,但这是一种方式。

分别处理日期和值,

#for date
df.date<-df%>%select(id, age,date1,date2, date3)%>%melt(id.var=c("id", "age"), value.name="date")
#for val
df.val<-df%>%select(id, age,value1,value2, value3)%>%melt(id.var=c("id", "age"), value.name="value")

现在加入,

df2<-full_join(df.date, df.val, by=c("id", "age"))
df2%>%select(-variable.x, -variable.y)

 id age       date value
1   1  40 2015-07-19    28
2   1  40 2015-07-19    49
3   1  40 2015-07-19    24
4   2  33 2015-06-27    99
5   2  33 2015-06-27    18
6   2  33 2015-06-27    26
7   3  75 2015-07-07    63
8   3  75 2015-07-07    74
9   3  75 2015-07-07    72

答案 1 :(得分:1)

我偶然发现了这个尝试了解如何使用gather混合使用日期和值。

现有答案会丢失有关日期 - 值对来自哪个实例的信息,即date1&amp;的实例1。 value1等。这可能并不重要,但这里有一个保持实例的tidyverse选项。

library(stringr) # not necessary but nice
library(tidyr)
library(dplyr)

df %>% 
    gather(key, val, -id, -age) %>% 
    mutate(
        measure = str_sub(key,1,-2), 
        instance = str_sub(key, -1)
    ) %>% 
    select(-key) %>% 
    spread(measure, val) %>% 
    mutate(date = as.Date(date, origin="1970-01-01")) # restore date class

答案 2 :(得分:1)

我对我正在处理的数据集有完全相同的问题和数据格式。在工作中众包答案。我们中的一些人想出了一个tidyrdplyr管道解决方案。使用与原始问题相同的模拟 df

df %>%
    gather(key = date_position, value = date, starts_with("date")) %>%
    gather(key = value_position, value = value, starts_with("value")) %>%
    mutate(date_position = gsub('[^0-9]', "", date_position),
           value_position = gsub('[^0-9]', "", value_position)) %>%
    filter(date_position == value_position) %>%
    select(-ends_with("position")) %>%
    arrange(id)

答案 3 :(得分:0)

相同的策略,但使用tidyr代替如下:

df.value <- df %>%
    gather(key="foo", value="value", starts_with("value"))
df.date <- df %>%
    gather(key="bar", value="date", starts_with("date"))

控制结果维度后(注意NA值 - na.rm函数还有一个gather参数)我使用base / dplyr函数加入了data.frames:< / p>

df.long <- data.frame(select(df.value, id, age, value), select(df.date, date))

我确信这两个部分都有更加优雅的方式,但它确实可以解决问题。

答案 4 :(得分:0)

这会执行reshape,然后对行进行排序。

前两行只是为v.names设置varyingreshape参数。 v.names定义了新的列名称,varying是一个列表,其中两个组件分别包含datevalue列的逻辑选择向量。

最后一行代码执行排序,如果行顺序无关紧要,可以省略。

没有使用任何包裹。

v.names <- c("date", "value")
varying <- lapply(v.names, startsWith, x = names(df))
r <- reshape(df, dir = "long", varying = varying, v.names = v.names)
r[order(r$id, r$time), ]

给出以下内容,其中id和time列将输出行与输入相关联:

     id age time       date value
1.1   1  12    1 2015-08-14     3
1.2   1  12    2 2015-07-11    24
1.3   1  12    3 2015-07-04     4
2.1   2  92    1 2015-08-03    17
2.2   2  92    2 2015-07-19    52
2.3   2  92    3 2015-07-01    93
3.1   3  28    1 2015-08-24    86
3.2   3  28    2 2015-08-12    80
3.3   3  28    3 2015-09-01    56
4.1   4  45    1 2015-09-13    78
4.2   4  45    2 2015-07-07    92
4.3   4  45    3 2015-08-10    81
5.1   5  25    1 2015-08-27    95
5.2   5  25    2 2015-09-08    68
5.3   5  25    3 2015-06-27    82
6.1   6   1    1 2015-08-21    16
6.2   6   1    2 2015-06-15    35
6.3   6   1    3 2015-07-24    30
7.1   7   7    1 2015-07-19    59
7.2   7   7    2 2015-07-08    33
7.3   7   7    3 2015-08-11    49
8.1   8  71    1 2015-07-28    19
8.2   8  71    2 2015-06-29    74
8.3   8  71    3 2015-08-05    25
9.1   9  59    1 2015-07-05    64
9.2   9  59    2 2015-09-04    30
9.3   9  59    3 2015-07-30    74
10.1 10  96    1 2015-09-12    69
10.2 10  96    2 2015-07-23    72
10.3 10  96    3 2015-08-19    23