【问题标题】:Data extraction/reshape from a data frame in R从 R 中的数据框中提取/重塑数据
【发布时间】:2016-03-29 09:32:38
【问题描述】:

我有一个数据框 - 您可以使用以下代码重新创建它的示例:

df = data.frame(M_id = c(rep(1000,8),rep(1001,8)), Day = c(rep(1,4),rep(2,4),rep(1,4),rep(2,4)), Half_hr = rep(1:4,4) ,Val = c(0.25,0.1,0.2,0.4,0.3,0.6,0.35,0.5,0.15,0.2,0.3,0.5,0.4,0.7,0.45,0.6))

看起来像这样:

>df : 

 M_id  Day  Half_hr     Val
 1000    1   1          0.25
 1000    1   2          0.1
 1000    1   3          0.2
 1000    1   4          0.4
 1000    2   1          0.3
 1000    2   2          0.6
 1000    2   3          0.35
 1000    2   4          0.5
 1001    1   1          0.15
 1001    1   2          0.2
 1001    1   3          0.3
 1001    1   4          0.5
 1001    2   1          0.4
 1001    2   2          0.7
 1001    2   3          0.45
 1001    2   4          0.6

这里,在每一行中,Val 代表该 M_id 在该 Half_hr 中的那一天的 Value(Half_hr:1,2 是第 1 小时,3,4 是第 2 小时,依此类推)。我的实际数据在 48 Half_hrs(24 小时)内有很多 Ids 和 Days 和 Val

现在,我想将每个 Half_hr 的数据汇总到每天每个 M_id 的每个小时中。

我的输出应该是这样的:

>df:

M_id    Day Hour_1  Hour_2
1000    1    0.35    0.6
1000    2    0.9     0.85
1001    1    0.35    0.8
1001    2    0.11    1.05

示例是 M_id = 1000,Day = 1,Hour_1 = Val(Half_hr-1 + Half_hr-2) = 0.25+0.1 = 0.35。同样对于 Hour_2 = val(Half_hr-3 + Half_hr-4) = 0.2+0.4 = 0.6

我已经使用 for 循环和 sqldf 完成了这项工作,但这需要花费很多时间。

我请求优化代码,因为我必须处理的数据有 1000 个 M_id,每个 535 天,每天 48 个 Half_hrs(24 小时数据)。

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    我们可以使用data.table。将'data.frame'转换为'data.table'(setDT(df)。按“M_id”、“Day”分组后使用gl创建分组变量,然后使用dcast将“long”转换为“宽'格式

    library(data.table)
    df1 <- setDT(df)[order(M_id,Day, Half_hr)][,
             gr:=gl(.N, 2, .N) , .(M_id ,Day)][]
    dcast(df1, M_id+Day~paste0("Hour_", gr), value.var="Val", sum)
    #   M_id Day Hour1 Hour2
    #1: 1000   1  0.35  0.60
    #2: 1000   2  0.90  0.85
    #3: 1001   1  0.35  0.80
    #4: 1001   2  1.10  1.05
    

    【讨论】:

    • 这是否假定Half_hr 已订购?
    • @RomanLuštrik 我之前是这么认为的,但是在您的评论 ordered 数据之后。
    【解决方案2】:

    这是使用 transform()aggregate()reshape() 在基础 R 中的解决方案:

    reshape(aggregate(Val~.,transform(df,Hour=(Half_hr-1L)%/%2L+1L,Half_hr=NULL),sum),dir='w',idvar=c('M_id','Day'),timevar='Hour');
    ##   M_id Day Val.1 Val.2
    ## 1 1000   1  0.35  0.60
    ## 2 1001   1  0.35  0.80
    ## 3 1000   2  0.90  0.85
    ## 4 1001   2  1.10  1.05
    

    【讨论】:

    • 它也很好用。但是相对于 data.table 的解决方案对我的数据来说速度很快。非常感谢。
    猜你喜欢
    • 2011-12-05
    • 2017-02-11
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    相关资源
    最近更新 更多