【问题标题】:How to find sum and average for some columns based on the numbers from another column in R如何根据R中另一列的数字查找某些列的总和和平均值
【发布时间】:2014-01-22 00:59:23
【问题描述】:

给定数据

我有6列车辆轨迹数据(观察车辆位置、速度等随时间的变化),其中一部分如下所示:

Vehicle ID Frame ID Global X Vehicle class Vehicle velocity Lane
          1      177  6451181             2            24.99    5
          1      178  6451182             2            24.95    5
          1      179  6451184             2            24.91    5
          1      180  6451186             2            24.90    5
          1      181  6451187             2            24.96    5
          1      182  6451189             2            25.08    5

车辆 ID 是单个车辆的标识,例如车辆 1、车辆 2 等。对于观察到的每个帧,它在列中重复。请注意,每帧长度为 0.1 秒,因此 10 帧等于 1 秒。框架的 ID 在框架 ID 列中。车辆类别是车辆的类型(1=摩托车,2=汽车,3=卡车)。车辆速度列表示车辆在该时刻即帧中的瞬时速度。 Lane 表示特定帧中车辆所在车道的编号或 ID。

我需要找到什么

我拥有的数据是 15 分钟。最小帧 ID 为 5,最大帧 ID 为 9952。我需要找到每 30 秒时间段内的车辆总数。这意味着从前 30 秒(帧 ID 5 到帧 ID 305)开始,我需要知道观察到的唯一车辆 ID。此外,对于这 30 秒的时间段,我需要找到每个车辆类别的平均速度。这意味着例如对于汽车,我需要找到车辆等级为 2 的车辆的所有速度的平均值。 我需要在所有 30 秒的时间段内找到它,即 5-305、305-605、605-905、...、9605-9905。汽车、卡车和摩托车的输出应该是这样的:

Time Slots   Total Cars   Average Velocity
5-305   xx   xx  
305-605   xx   xx
.   .   .
.   .   .
9605-9905   xx   xx 

到目前为止我已经尝试过什么

# Finding the minimum and maximum Frame ID for creating 30-seconds time slots
minfid <- min(data$'Frame ID') # this was 5
maxfid <- max(data$'Frame ID') # this was 9952

for (i in 'Frame ID'==5:Frame ID'==305) {
table ('Vehicle ID')
mean('Vehicle Velocity', 'Vehicle class'==2)
}   #For cars in first 30 seconds

我无法生成所需的输出,也不知道如何在所有 30 秒的时间段内执行此操作。请帮忙。

【问题讨论】:

    标签: r sum mean


    【解决方案1】:

    要确保代码与您的数据完全正确有点困难,因为您展示的示例中只有一辆车。也就是说,这是一个典型的拆分-应用-组合类型分析,您可以使用 data.table 包轻松执行:

    library(data.table)
    dt <- data.table(df)  # I just did a `read.table` on the text you posted
    dt[, frame.group:=cut(Frame_ID, seq(5, 9905, by=300), include.lowest=T)]
    

    在这里,我只是将您的数据转换为 data.table(df 是您上面发布的数据的直接导入),然后使用 cut 创建了 300 个帧存储桶。然后,您只需让data.table 完成工作。在第一个表达式中,我们计算每个 frame.group 的唯一车辆总数

    dt[, list(tot.vehic=length(unique(Vehicle_ID))), by=frame.group]
    #    frame.group tot.vehic
    # 1:     [5,305]         1  
    

    现在我们按frame.groupVehicle_class 分组以获得这些组合的平均速度和计数:

    dt[, list(tot.vehic=length(unique(Vehicle_ID)), mean.speed=mean(Vehicle_velocity)), by=list(frame.group, Vehicle_class)]
    #    frame.group Vehicle_class tot.vehic mean.speed
    # 1:     [5,305]             2         1     24.965
    

    同样,当我们只有一辆车时有点傻,但这应该适用于您的数据集。


    编辑:表明它有效:

    library(data.table)
    set.seed(101)
    dt <- data.table(
      Frame_ID=sample(5:9905, 50000, rep=T), 
      Vehicle_ID=sample(1:400, 50000, rep=T),
      Vehicle_velocity=runif(50000, 25, 100)
    )
    dt[, frame.group:=cut(Frame_ID, seq(5, 9905, by=300), include.lowest=T)]
    dt[, Vehicle_class:=Vehicle_ID %% 3]
    head(
      dt[order(frame.group, Vehicle_class), list(tot.vehic=length(unique(Vehicle_ID)), mean.speed=mean(Vehicle_velocity)), by=list(frame.group, Vehicle_class)]
    )
    #    frame.group Vehicle_class tot.vehic mean.speed
    # 1:     [5,305]             0       130   63.34589
    # 2:     [5,305]             1       131   61.84366
    # 3:     [5,305]             2       129   64.13968
    # 4:   (305,605]             0       132   61.85548
    # 5:   (305,605]             1       132   64.76820
    # 6:   (305,605]             2       133   61.57129
    

    也许是你的数据?

    【讨论】:

    • +1 用于使用 cut 并将分析变量与数据一起存储。
    • 非常感谢@BrodieG 提供的解决方案。我也尝试了第二种解决方案,但不幸的是,我得到的结果是所有 300 帧时隙的车辆数量相同(1774 辆)。我确信情况并非如此。我认为它给了我所有帧组合中的车辆总数,而不是在 300 帧时间段中观察到的车辆数量。这意味着输出中的“tot.veh”列的总和应为 1774,但每行都给我 1774。我该如何解决这个问题?
    • @umairdurrani,我认为更新显示代码按预期工作。我建议您检查 data.table 的一个帧组,并确认它与您认为的完全一致。
    • @BrodieG 谢谢,它有效。我多次阅读 data.table 文档并将您的代码用于小数据,我了解它现在是如何工作的。如果 frame.group 中的最后一个间隔长度小于 300 帧怎么办?在我的原始数据集中,最大帧为 9952。cut() 创建最后一个间隔为 9605-9905。在 9905-9952 区间内还剩下 47 帧。我怎样才能包含它?
    • @umairdurrani,你应该可以做到c(seq(5, 9905, by=300), 9952)
    【解决方案2】:

    这是plyr 版本:

    data$timeSlot <- cut(data$FrameID, 
                         breaks = seq(5, 9905, by=300), 
                         dig.lab=5, 
                         include.lowest=TRUE)
    
    # split & combine
    library(plyr)
    data.sum1 <- ddply(.data = data, 
                    .variables = c("timeSlot"), 
                    .fun = summarise, 
                       totalCars = length(unique(VehicleID)),
                       AverageVelocity = mean(velocity)
                    )
    
    
    # include VehicleClass
    data.sum2 <- ddply(.data = data, 
                       .variables = c("timeSlot", "VehicleClass"), 
                       .fun = summarise, 
                         totalCars = length(unique(VehicleID)),
                         AverageVelocity = mean(velocity)
    )
    

    FrameID 等列名必须进行编辑以匹配您使用的列名:

    data <- read.table(sep = "", header = TRUE, text = "
    VehicleID FrameID GlobalX VehicleClass velocity Lane
     1 177 6451181 2 24.99 5
     1 178 6451182 2 24.95 5
     1 179 6451184 2 24.91 5
     1 180 6451186 2 24.90 5
     1 181 6451187 2 24.96 5
     1 182 6451189 2 25.08 5") 
    data.sum1
    #   timeSlot totalCars AverageVelocity
    # 1  [5,305]         1          24.965
    
    data.sum2
    #   timeSlot VehicleClass totalCars AverageVelocity
    # 1  [5,305]            2         1          24.965
    

    【讨论】:

    • +1 用于建议cut 它可以保持分析与数据不重复
    • 我认为休息应该是:seq(5, 9905, length.out=33) 或像 BrodieG 的示例 seq(5, 9905, length.out=33), include.lowest=TRUE),否则 5 和 9905 将获得 NA。
    • @BrandonBertelsen Nooo 我从 BrodieG 那里偷的 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    相关资源
    最近更新 更多