【问题标题】:How to fill in a field based on conditional subsetting from 2 other fields如何根据其他 2 个字段的条件子集填写字段
【发布时间】:2015-04-09 14:13:45
【问题描述】:

我有一个看起来像这样的数据框

vessday  gearval  gear  otherfields
152      1        OTB   a
152      0        NA    b
152      1        OTB   c
152      1        HMD   b
152      0        NA    e
153      1        OTT   f
153      1        OTT   g
153      0        NA    h

我想在我的数据框中添加一个字段gearkey,并为每个vessday 填充最频繁的gear,不计算NA(因此,当gearval==1 时)。 otherfields 表示数据有其他字段的负载,并且没有重复的行。

我希望我的数据框如下所示,但真正的数据框有 250 万条记录和几千条唯一的 vessdays。

vessday  gearval  gear  otherfields  gearkey
152      1        OTB   a            OTB   
152      0        NA    b            OTB   
152      1        OTB   c            OTB   
152      1        HMD   b            OTB   
152      0        NA    e            OTB   
153      1        OTT   f            OTT   
153      1        OTT   g            OTT
153      0        NA    h            OTT

我认为我得到的最接近的是这个

data$gearkey[unique(data$vessday) & data$gearval==1] <- mode(data$gear)

但我得到了错误

较长的对象长度不是较短对象长度的倍数

现在,我的大脑变成了糊状豌豆,我不知道该怎么做...任何帮助将不胜感激!

更新

我可能有点过早地接受了@akrun 的回答:他的base R 行产生了所需的输出,但我的每个数据集(其中我有几个)需要 2 个多小时。所以,不好。

在我的数据上去掉时间类之后,我尝试了dplyr 块,虽然它似乎产生了正确的结果,但我不能让mutate 用新列更新我的数据(仍然不要不知道为什么)。

所以,最终尝试了一条不同的路线,这很有效(每个文件不到 10 分钟),并且似乎不打扰时间类:

library(data.table)

Mode <- function(x, na.rm=T) {
        if(na.rm){
            x = x[!is.na(x)]
        }
        ux <- unique(x)
        ux[which.max(tabulate(match(x, ux)))]
    }

df1 <- data.table(df1)
df1[, `:=`(newgear=Mode(gear), by="vessday"]

【问题讨论】:

    标签: r conditional subset


    【解决方案1】:

    你可以试试

    library(dplyr)
    
    Mode <- function(x) {
       ux <- unique(x)
       ux[which.max(tabulate(match(x, ux)))]
     } 
    
    df1 %>% 
        group_by(vessday) %>% 
        mutate(gearkey= Mode(gear))
    
    #    vessday gearval gear otherfields gearkey
    #1     152       1  OTB           a     OTB
    #2     152       0   NA           b     OTB
    #3     152       1  OTB           c     OTB
    #4     152       1  HMD           b     OTB
    #5     152       0   NA           e     OTB
    #6     153       1  OTT           f     OTT
    #7     153       1  OTT           g     OTT
    #8     153       0   NA           h     OTT
    

    或使用base R

    df1$gearkey <-  with(df1, ave(gear, vessday, FUN=function(x) Mode(x)))
    df1$gearkey
    #[1] "OTB" "OTB" "OTB" "OTB" "OTB" "OTT" "OTT" "OTT"
    

    更新

    @Catarina Aires 对Mode 的修改版

      Mode <- function(x, na.rm = T) { 
                if(na.rm){
                   x = x[!is.na(x)] }
              ux <- unique(x)
              ux[which.max(tabulate(match(x, ux)))] }
    

    数据

    df1 <- structure(list(vessday = c(152L, 152L, 152L, 152L, 152L, 153L, 
    153L, 153L), gearval = c(1L, 0L, 1L, 1L, 0L, 1L, 1L, 0L), gear = c("OTB", 
    NA, "OTB", "HMD", NA, "OTT", "OTT", NA), otherfields = c("a", 
    "b", "c", "b", "e", "f", "g", "h")), .Names = c("vessday", "gearval", 
    "gear", "otherfields"), class = "data.frame", row.names = c(NA, -8L))
    

    【讨论】:

    • 谢谢阿克伦。很想尝试您的建议,但无法安装 dplyr 包:它说“依赖项'BH'不适用于包”。必须先对其进行排序。
    • @CatarianAires 您可以在基础 R 中执行此操作。我认为使用大型数据集使用 dplyr 或 data.table 会更容易。 base R 中的相同代码将是 df1$gearkey &lt;- with(df1, ave(gear, vessday, FUN=function(x) Mode(x)))
    • 设法安装了 BH 和 dplyr,但我的 otherfields 之一是 time,times 类型似乎不受支持。
    • 我已经尝试过您的其他建议,但它只是将gear 列复制到gearkey。明天我真得用新的眼光看待这个,但你让我深思!非常感谢!
    • @CatarinaAires 如果不支持,可以试试ave 代码。 ave 根据我帖子中的数据工作。你能用示例数据检查一下吗
    猜你喜欢
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    相关资源
    最近更新 更多