【问题标题】:Combine and average each 15 data.frames from a list合并并平均列表中的每 15 个数据帧
【发布时间】:2018-06-03 03:54:24
【问题描述】:

我的数据集是一个包含 1000 个 data.frame(“sportdata”)类型元素的列表。列表的每个 data.frame 元素代表一分钟的数据,并且具有完全相同的列数和名称,每个 data.frame 最多有 45 个 ID(即 45 行,但在某些分钟内缺少一个或多个 ID,所以它可能是例如 35 行)。 我想对每 15 个 data.frames 的完整数据集进行组合和平均,将其添加到一个 data.frame 中并转置 data.frame,以便将 ID 作为列,将每 15 分钟的平均 SpeedKph 作为行。

我的 data.frames 列表如下所示:

head(sportdata)
        [[1]]
                ID  Distance SpeedKph
         1:     1     2247       73
         2:     2     2247       73
         3:     3     1970       73
         4:     4     1964       74 
         5:     5     1971       73 
        [[2]]
                ID  Distance SpeedKph
         1:     1     2247       73
         2:     2     2247       75
         3:     3     1970       73
         4:     4     1964       74 
         5:     5     1971       73 
        [[3]]
                ID  Distance SpeedKph
         1:     1     2247       73
         2:     2     2247       80
         3:     3     1970       73
         4:     4     1964       74 
         5:     5     1971       56 

我有下面的代码来组合和平均列表中的所有 data.frame,但我还没有找到一种方法来组合和平均每 15 个元素(即 15 分钟)的列表并将其添加到一个数据中。框架。

dfTotal <- rbindlist(sportdata)[,lapply(.SD,mean), list(ID)]    

我希望我的理想输出 data.frame 看起来像:

   #ofData.Frames |   1   |  2  |  3  |...etc.
         01-15:      73     74    74
         16-30:      75     77    74
         31-45:      74     74    79
         46-60:      78     72    74
         ...etc.

提前感谢您的帮助!

更新 很抱歉没有直接这样做,这是我可重现的示例。

my.df1 <- data.frame(ID = c(1:5),
                    Distance = c(2247,2247,1970,1964,1971),
                    SpeedKph = c(73,73,74,73,75))
my.df2 <- data.frame(ID = c(1:5),
                     Distance = c(2247,2247,1970,1964,1971),
                     SpeedKph = c(73,73,74,73,75))
my.df3 <- data.frame(ID = c(1:5),
                     Distance = c(2247,2247,1970,1964,1971),
                     SpeedKph = c(75,70,80,71,83))

my.list <- list(list1 = my.df1, list2 = my.df2, list3 = my.df3) 

【问题讨论】:

    标签: r list data.table


    【解决方案1】:

    data.table(您已经在使用)的可能解决方案:

    DT <- rbindlist(my.list, idcol = 'id')
    
    DT[, grp := (id - 1) %/% 3
       ][, c(frames = toString(id), lapply(.SD, mean)), by = .(grp, ID), .SDcols = 3:4
         ][, dcast(.SD, frames ~ ID, value.var = c('Distance','SpeedKph'))]
    

    给出:

        frames Distance_1 Distance_2 Distance_3 Distance_4 Distance_5 SpeedKph_1 SpeedKph_2 SpeedKph_3 SpeedKph_4 SpeedKph_5
    1: 1, 2, 3       2247   2247.000   1970.000   1964.000       1971   73.66667   72.00000   76.00000   72.33333   77.66667
    2: 4, 5, 6       2229   2410.333   1962.667   1964.333       1966   74.66667   73.66667   77.33333   72.33333   77.66667
    

    扩展示例数据:

    my.df1 <- data.frame(ID = c(1:5), Distance = c(2247,2247,1970,1964,1971), SpeedKph = c(73,73,74,73,75))
    my.df2 <- data.frame(ID = c(1:5), Distance = c(2247,2247,1970,1964,1971), SpeedKph = c(73,73,74,73,75))
    my.df3 <- data.frame(ID = c(1:5), Distance = c(2247,2247,1970,1964,1971), SpeedKph = c(75,70,80,71,83))
    my.df4 <- data.frame(ID = c(1:5), Distance = c(2247,2137,1948,1965,1971), SpeedKph = c(73,78,74,73,71))
    my.df5 <- data.frame(ID = c(1:5), Distance = c(2223,2247,1970,1964,1971), SpeedKph = c(76,73,74,73,79))
    my.df6 <- data.frame(ID = c(1:5), Distance = c(2217,2847,1970,1964,1956), SpeedKph = c(75,70,84,71,83))
    
    my.list <- list(my.df1, my.df2, my.df3, my.df4, my.df5, my.df6) 
    


    回应评论:

    # create some extra example data
    my.df4a <- my.df4[-4,]
    my.df5a <- my.df5[-c(4,5),]
    my.df6a <- my.df6[-c(3,4),]
    my.df7 <- my.df4[-c(4:6),]
    my.df8 <- my.df5[-c(4:6),]
    my.df9 <- my.df6[-c(4:6),]
    
    # make another list of 9 dataframes
    my.list2 <- list(my.df1, my.df2, my.df3, my.df4a, my.df5a, my.df6a, my.df7, my.df8, my.df9) 
    
    # bind that list together in one data.table
    DT2 <- rbindlist(my.list2, idcol = 'dfid')
    
    # do an 'expand join' with 'CJ' and add the original transformation
    DT2[CJ(dfid = dfid, ID = ID, unique = TRUE), on = .(dfid, ID)
        ][, grp := (dfid - 1) %/% 3
          ][, c(frames = toString(dfid), lapply(.SD, mean, na.rm = TRUE)), by = .(grp, ID), .SDcols = 3:4
            ][, dcast(.SD, frames ~ ID, value.var = c('Distance','SpeedKph'))]
    

    这给出了:

        frames Distance_1 Distance_2 Distance_3 Distance_4 Distance_5 SpeedKph_1 SpeedKph_2 SpeedKph_3 SpeedKph_4 SpeedKph_5
    1: 1, 2, 3       2247   2247.000   1970.000       1964     1971.0   73.66667   72.00000   76.00000   72.33333   77.66667
    2: 4, 5, 6       2229   2410.333   1959.000        NaN     1963.5   74.66667   73.66667   74.00000        NaN   77.00000
    3: 7, 8, 9       2229   2410.333   1962.667        NaN        NaN   74.66667   73.66667   77.33333        NaN        NaN
    


    关于行序:

    my.df10 <- my.df4
    my.df11 <- my.df5
    my.df12 <- my.df6
    
    my.list3 <- list(my.df1, my.df2, my.df3, my.df4a, my.df5a, my.df6a, my.df7, my.df8, my.df9, my.df10, my.df11, my.df12) 
    
    DT3 <- rbindlist(my.list3, idcol = 'dfid')
    
    DT3[CJ(dfid = dfid, ID = ID, unique = TRUE), on = .(dfid, ID)
        ][, grp := (dfid - 1) %/% 3
          ][, c(frames = toString(dfid), lapply(.SD, mean, na.rm = TRUE)), by = .(grp, ID), .SDcols = 3:4
            ][, dcast(.SD, grp + frames ~ ID, value.var = c('Distance','SpeedKph'))]
    

    这给出了:

       grp     frames Distance_1 Distance_2 Distance_3 Distance_4 Distance_5 SpeedKph_1 SpeedKph_2 SpeedKph_3 SpeedKph_4 SpeedKph_5
    1:   0    1, 2, 3       2247   2247.000   1970.000   1964.000     1971.0   73.66667   72.00000   76.00000   72.33333   77.66667
    2:   1    4, 5, 6       2229   2410.333   1959.000        NaN     1963.5   74.66667   73.66667   74.00000        NaN   77.00000
    3:   2    7, 8, 9       2229   2410.333   1962.667        NaN        NaN   74.66667   73.66667   77.33333        NaN        NaN
    4:   3 10, 11, 12       2229   2410.333   1962.667   1964.333     1966.0   74.66667   73.66667   77.33333   72.33333   77.66667
    

    【讨论】:

    • 嗨 Jaap,您的解决方案几乎就是我需要的,只是在缺少数据时不起作用;例如当(在此示例中)“my.df”之一的观测值少于 5 时。如果在该 ID 的三个组合 data.frame 中的任何一个中没有观察到,我将我的最终 data.frame 显示 NA,如果只有一个观察,我希望它说明该观察,如果有两个观察,我会喜欢它来说明两次观察的平均值。你能帮我解决这个问题吗?
    • 非常感谢 :) 我不知道从哪里开始,如何在代码中添加少于三个观察值的 NA/平均值,以便每行保留三个 data.frames(目前它创建如果缺少数据,则新行)?
    • @RobinNico 查看更新;这就是你要找的东西吗?
    • 太棒了!关于排序行和列的最后两个问题: - 列:我在向量“columnorder”中有列名,所以我尝试用这段代码对它们进行排序:DT2 &lt;- setcolorder(DT2,columnorder)。这以前有效,但是,不,它没有。你知道为什么吗? - 行:我想使用例如数据集升序排列我的行列表中的 12 个 data.frames 顺序变得混乱(首先是 123,然后是 10-11-12,然​​后是 456,等等),因为 R 根据第一个数字对其进行排序。有没有一种简单的方法可以根据原始订单(123、456、789、10-11-12)进行订购?非常感谢!
    • @RobinNico setcolorder(DT2,columnorder) 应该可以工作,但是如果您尝试使用原始文件中的列名重置结果中的列顺序,它将不起作用,因为这些名称不存在于结果数据中。桌子。关于行顺序,您可以尝试将dcast-part 更改为:dcast(.SD, grp + frames ~ ID, value.var = c('Distance','SpeedKph'))。请让我知道这是否有效(我自己还没有尝试过)
    【解决方案2】:

    获得完整数据集后,请尝试以下操作:

    将数据帧缩短 15 秒

    首先添加一列1:nrow(df),我们将在本例中使用1:1000

    require(tidyverse)    
    
    DF <- data.frame(mean_speed = sample(40:100, 1000, replace = TRUE))
    
    DF2 <- DF %>%
       mutate(index = 1:nrow(.),
       group = cut(index, c(seq(0, nrow(.), 15), nrow(.)))) %>%
       group_by(group) %>%
       mutate(row_num = row_number()) %>%
       select(-index) %>%
       spread(row_num, mean_speed)
    

    我们最终将行切割成一个以 15 秒为间隔的序列。然后我们按它分组并设置行号。这将为每个组添加1:15。然后我们要取消选择除组和均值之外的所有内容。最后,我们传播以将格式移动到宽。

    编辑:鉴于您的更新信息。我会尝试以下方法:

    DF2 <- dfTotal %>%
      mutate(group = cut(ID, c(seq(0, nrow(.), 15), nrow(.)))) %>%
      group_by(group) %>%
      select(-Distance) %>%
      spread(ID, SpeedKph)
    

    我不确定的一件事是,在您的较大数据框中,ID 是 1:1000,还是 1:15。如果您可以为您的数据集提供 50 行,那将有所帮助。如果 ID 为 1:15,您应该可以使用上面的代码。如果是 1:1000,则需要添加 mutate(row_num = row_number())

    【讨论】:

    • 谢谢马特!您能否详细说明第一步:DF
    • 当然 - 那是在您发布一些数据之前。我将它用作虚拟 DF,只是为了展示如何操作外观相似的数据帧的逻辑。您将忽略该部分并将其他代码应用于您自己的数据集。
    • 我认为您误解了我的问题/我不够清楚。我的数据集是一个包含 1000 个 data.frame 类型元素的列表。每个 data.frame 最多有 45 个 ID(即 45 行,但有时会丢失一个或多个 ID,因此它可能是例如 35 行)。我想将每 15 个 data.frames 的完整数据集组合和平均,将其添加到一个 data.frame 中并转置 data.frame,以便我将 ID 作为列,将每 15 分钟的平均 SpeedKph 作为行。我也会编辑并澄清我最初的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 2022-11-29
    • 1970-01-01
    • 2017-07-20
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多