我有一个数据框和许多条件。每个条件都应该检查数据帧某一列中的值是否在一组有效值之内。
这是我尝试的:
# create the sample dataframe
age <- c(120, 45)
sex <- c("x", "f")
df <-data.frame(age, sex)
# create the sample conditions
conditions <- list(
list("age", c(18:100)),
list("sex", c("f", "m"))
)
addIndicator <- function (df, columnName, validValues) {
indicator <- vector()
for (row in df[, toString(columnName)]) {
# for some strange reason, %in% doesn't work correctly here, but always returns FALSe
indicator <- append(indicator, row %in% validValues)
}
df <- cbind(df, indicator)
# rename the column
names(df)[length(names(df))] <- paste0("I_", columnName)
return(df)
}
for (condition in conditions){
columnName <- condition[1]
validValues <- condition[2]
df <- addIndicator(df, columnName, validValues)
}
print(df)
但是,这导致所有条件都无法满足-这不是我期望的:
age sex I_age I_sex
1 120 x FALSE FALSE
2 45 f FALSE FALSE
我认为这%in%
不会返回预期的结果。我检查了typeof(row)
并尝试将其简化为一个最小示例。在具有相同类型和变量值的简单ME中,%in%
工作正常。因此,在我尝试应用的上下文中一定有问题。由于这是我第一次尝试在R中编写任何内容,因此我被困在这里。
我做错了什么,我怎么能实现自己想要的?
如果您更喜欢使用tidyverse系列软件包的方法:
library(tidyverse)
allowed_values <- list(age = 18:100, sex = c("f", "m"))
df %>%
imap_dfr(~ .x %in% allowed_values[[.y]]) %>%
rename_with(~ paste0('I_', .x)) %>%
bind_cols(df)
imap_dfr
允许您df
使用lambda函数操作每一列。.x
引用列内容并.y
引用名称。
rename_with
使用另一个lambda函数重命名列,bind_cols
并将结果与原始数据框合并。
我从ben的答案中借用了简化的条件清单。我发现我的方法更具可读性,但这是一个问题,取决于您是否已经在其他地方使用了tidyverse。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句