如何根据 2 个其他字段的条件子集来填写字段

How to fill in a field based on conditional subsetting from 2 other fields

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

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)

但是我收到错误

longer object length is not a multiple of shorter object length

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

更新

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

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

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

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"]

你可以试试

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))