【问题标题】:Replace some character by NA data.table用 NA data.table 替换一些字符
【发布时间】:2017-11-06 13:00:48
【问题描述】:

我正在构建一个函数来将一些字符(如“-”)替换为 R 中 data.table 内的正确 NA

我的功能如下:

na_replacer <- function(data_set, characters_to_replace) {
  text_features <- names(data_set)[sapply(data_set, class) %in% c("character","factor")]
  for (x in text_features) {
    data_set[, lapply(.SD, function(x) replace(x, which(x==any(characters_to_replace)), NA))]
  }
  return (data_set)
}

当我运行这个函数时,我得到了以下异常:

charToDate(x) 中的错误:
字符串不在标准中 明确的格式

你能帮我让这个功能按预期工作吗?或者也许有一个更短的版本来做我尝试执行的操作?

这是一个调用函数的示例数据集

DT = data.table(ID = c("foo","bar","-","foo","[]","bah"), a = 1:6, b = 7:12, c = 13:18, d = c("aaa", "bbb", "ccc", "_", "eeee", "ffff"))
DT <- na_replacer(data_set = DT, characters_to_replace = c('-', '_', '[]'))

之前的数据集:

    ID a  b  c    d
1: foo 1  7 13  aaa
2: bar 2  8 14  bbb
3:   - 3  9 15  ccc
4: foo 4 10 16    _
5:  [] 5 11 17 eeee
6: bah 6 12 18 ffff

之后的预期数据集:

    ID a  b  c    d
1: foo 1  7 13  aaa
2: bar 2  8 14  bbb
3:  NA 3  9 15  ccc
4: foo 4 10 16   NA
5:  NA 5 11 17 eeee
6: bah 6 12 18 ffff

【问题讨论】:

  • 这不适合你吗? gsub('-','NA',df$text)
  • edit您的问题并添加minimal reproducible example。谢谢。
  • @Uwe 我添加了一个具有预期输出的可验证样本。我希望这会更好;谢谢
  • 这个data.table是怎么创建的?如果从文件中读取,您可以使用fread() 和参数na.strings = c('-', '_', '[]')
  • 确实,数据是从文件中读取的,但是我想将 NA 解析限制为“字符”和“因子”。此外,在我的管道中,NA 是作为数据转换的结果引入的(不是 NA,而是其他字符)。尽管如此,我将使用您的建议来替换初始 NA。谢谢

标签: r data.table na


【解决方案1】:

请测试在data.table 上运行的修改后的函数。

na_replacer <- function(data_set, characters_to_replace = c('-', '_')) {
    library(data.table)
    setDT(data_set)
    text_features <- names(data_set)[sapply(data_set, class) %in% c("character", "factor")]
    for (x in text_features) {
        foo <- data_set[, get(x)]
        data_set[, eval(x) := ifelse(foo %in% characters_to_replace, NA, foo)]
    }
    return(data_set)
}

【讨论】:

  • @Michael 乐于助人 :-)
  • 抱歉,快速提问,我看到您使用 eval()get() 是什么让它们不同?
  • @Michael 很快,get 查找现有对象(在本例中为 data.table 列),eval 评估新表达式
  • 谢谢,感谢您的帮助。
  • @Michael 如果解决了你的问题,你可以接受我的解决方案
【解决方案2】:

OP 已请求将 data.table 的 characterfactor 类型的所有列中的某些字符串替换为 NA

previously accepted answer 在因子列中失败。

以下两种方法也适用于因子列:

加入更新

library(data.table)
options(datatable.print.class = TRUE)

for (col in DT[, names(.SD)[lapply(.SD, class) %in% c("character", "factor")]]) {
  DT[.(chr = c("-", "_", "[]")), on = paste0(col, "==chr"), (col) := NA_character_][]
}
DT
       ID     a     b     c      d
   <char> <int> <int> <int> <fctr>
1:    foo     1     7    13    aaa
2:    bar     2     8    14    bbb
3:     NA     3     9    15    ccc
4:    foo     4    10    16     NA
5:     NA     5    11    17   eeee
6:    bah     6    12    18   ffff

使用set()

for (col in DT[, names(.SD)[lapply(.SD, class) %in% c("character", "factor")]]) {
  set(DT, DT[get(col) %in% c("-", "_", "[]"), which = TRUE], col, NA_character_)
}
DT
       ID     a     b     c      d
   <char> <int> <int> <int> <fctr>
1:    foo     1     7    13    aaa
2:    bar     2     8    14    bbb
3:     NA     3     9    15    ccc
4:    foo     4    10    16     NA
5:     NA     5    11    17   eeee
6:    bah     6    12    18   ffff

数据

OP 在最新更新中提供的示例数据集正在使用,但有一处修改:列 d 被强制转换为 factor

DT <- data.table(ID = c("foo", "bar", "-", "foo", "[]", "bah"), 
                 a = 1:6, b = 7:12, c = 13:18, 
                 d = factor(c("aaa", "bbb", "ccc", "_", "eeee", "ffff")))

【讨论】:

  • 谢谢,这太棒了!它确实比原来的答案更好 - 一个问题,你为什么使用“NA_character_”而不是简单的 NA?从可读性的角度来看,我更喜欢set() 版本。
  • NA 是逻辑类型,但列类型分别是 characterfactor 类型。 data.table 的优点之一是它可以就地更新,即无需复制整个列或数据对象。如果替换列的选定元素,则类型必须匹配。 data.table 对此进行检查。顺便提一句。我已经看到使用数字常量的基准,例如1,而不是整数常量 1L 由于类型转换导致 15% 的性能损失。
【解决方案3】:

检查一下:

solution <- function(dt, replacer) {
  result <- do.call(cbind, lapply(dt, function(x) lapply(x, function(x) {  ifelse(is.na(x), replacer, x) } )))
  as.data.frame(result)
}

# example:
dt <- data.frame(x = c(1, 4, NA, NA, 54), y = c(5, NA, -1, 0, 5))
cat("before:")
dt
cat("after:")
solution(dt, "-")

它将所有NA 值替换为data.frame 中的给定符号。

【讨论】:

  • 这改变了类的性质 - 我想保留我的 data.table
  • 所以你可以在solution函数的最后一行做data.table(result)
【解决方案4】:

这样的东西能用吗

na_replacer <- function(data_set, characters_to_replace) {
  text_features <- names(data_set)[sapply(data_set, class) %in% c("character","factor")]
  for (x in text_features) {
    data_set[[x]][grep(paste0('[',characters_to_replace,']',collapse  =""),data_set[[x]])] <- NA
  }
  return (data_set)
}

【讨论】:

  • 我收到了一些警告,但我怀疑这不是问题 > 在 grep(paste0("[", characters_to_replace, "]"), data_set[[x]]) 中:参数 'pattern'长度 > 1 并且只使用第一个元素
  • 在粘贴语句中添加了参数请重试
  • 我现在没有坐在我的电脑旁,也许 collapse ="*" 效果更好
  • 这不起作用,“-”和“_”仍然存在于表中。我发现您的代码可读性较差,但功能更强大(我看到其他应用程序),您介意尝试使其工作并解释collapse 在做什么吗?
  • 如果你给 paste 一个像你的 characters_to_replace 这样的向量,它也会返回一个向量。在这种情况下,如果 characters_to_replace = c("","-")。 paste0('[',characters_to_replace,']',collapse ="") 返回 c("[]","[-]")。 collapse = "" 会将其简化为字符串 "[_][-]"。首先减少你的向量可能会更好。代码看起来像这样。 paste0("[",paste0(characters_to_replace,collapse = ""),"]")
猜你喜欢
  • 1970-01-01
  • 2014-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-25
  • 1970-01-01
  • 2022-07-15
  • 2020-03-24
相关资源
最近更新 更多