首页 > 解决方案 > 无法将 lapply 与 data.table 一起使用

问题描述

我正在尝试创建 data.table 中所有字符变量的摘要。基本上是为了获得总观察计数、缺失值、频率最高的类别等。但是我无法正确使用lapply相同的值。这是一个可重现的例子。

library(data.table)

#Function to analyze one variable at a time
analyze_char_var <- function(x) {
  y = names(x)
  z = x[,.N,by=y]
  w = setorder(z,-N)

  out = data.table( 
    total_obs = nrow(x),
    missing_obs = sum(is.na(x)),
    unique_cats = nrow(z),
    top_cat = z[1,1],
    top_freq = z[1,2]
  )
  return(out)
}
#Function to analyze all variables. I want to use lapply instead of loop
analyze_all_char <- function(dt) {
  dt.char = dt[,sapply(dt,class)=="character", with=FALSE]
  mylist = vector('list', length(dt.char))
  for (i in 1:length(dt.char)){
    x = dt.char[,i,with=FALSE]
    mylist[[i]] = analyze_char_var(x)
  }
  return(mylist)
}

dt = data.table(
  var1 = c('a', 'a', 'b','b', 'c'),
  var2 = 1:5,
  var3 = c('low','low','high','med',NA)
)
dt.analysis = analyze_all_char(dt)

只是使用dt.analysis = dt.char[,lapply(.SD,analyze_char_var)]会产生错误Error in x[, .N, by = y] : incorrect number of dimensions。我尝试了一些变化,但无法让它发挥作用。

编辑:最后这对我有用。但是,看起来很笨拙。将输入向量重新转换为 data.table,然后lapply以 data.frame 的方式使用。

test_func <- function(x) {
  dt = as.data.table(x)
  dt.summ = dt[,.N,by='x'] #by default name is x
  # I was stuck in the above line, I was trying all 
  # sort of bad tricks to get the name of grouping variable 


  dt.summ.sorted = setorder(dt.summ,-N)
  out = data.table(
    total_obs = nrow(dt),
    missing_obs = sum(is.na(dt)),
    unique_cats = nrow(dt.summ.sorted),
    top_cat = dt.summ.sorted[1,1],
    top_freq = dt.summ.sorted[1,2]
  )
  return(out)
}

dt.char = dt[,sapply(dt,class)=="character", with=FALSE]
lapply(dt.char,test_func)

标签: rdata.tablelapplysummarization

解决方案


我正在尝试创建 data.table 中所有字符变量的摘要。基本上是为了获得总观察计数、缺失值、频率最高的类别等。

由于所有感兴趣的列都具有相同的类型,因此您可以使用melt转到长格式:

melt(dt.char <- Filter(is.character, dt), meas=names(dt.char))[, {

  tabula = setDT(list(value))[, .N, by="V1"][order(-N, V1)]

  .(
    NOBS  = .N,
    NNA   = sum(is.na(value)),
    NVALS = nrow(tabula),
    HIVAL = tabula$V1[1L],
    NHI   = tabula$N[1L]
  )
}, by=variable]

#    variable NOBS NNA NVALS HIVAL NHI
# 1:     var1    5   0     3     a   2
# 2:     var3    5   1     4   low   2

要将 NA 排除为一个类别(出现在 NVALS 和可能的 HIVAL、NHI 中),请更改[, .N, by="V1"][!is.na(V1), .N, by="V1"]上述内容。

我怀疑性能对这项任务很重要,但这应该是相当有效的。


推荐阅读