如何根据 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 万条记录和几千条唯一 vessday
s。
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))
我有一个看起来像这样的数据框
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 万条记录和几千条唯一 vessday
s。
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))