R语言 如何提高函数的效率

koaltpgm  于 2023-04-03  发布在  其他
关注(0)|答案(2)|浏览(137)

我写这个函数是为了将一个包含分类变量的数据集(只包含观察到的分类组合)转换成一个包含所有可能的组合的数据集,这些组合是在考虑变量和分类的情况下找到的;此外,我还希望有一个列“y”,其中包含该行的频率,即我在原始数据集中观察到该模式的次数。

datafreq <- function(dati) {
  dati = na.omit(dati)
  dati[] = lapply(dati, factor)
  dati <-  dati %>%
    group_by_all(.drop = FALSE) %>%
    summarise(y = n()) %>%
    ungroup()
  return(as.data.frame(dati))
}

例如,您可以在UCI机器学习存储库https://archive.ics.uci.edu/ml/datasets/congressional+voting+records中找到数据集votes
它有435行,每行包含16个分类变量的值的组合。
我想得到一个3^16行的数据集,每一行对应于变量类别的每个组合(观察到的和未观察到的)(每个变量有3个可能的类别)。应该创建一个变量y,用于计算数据中每个组合被观察到的次数(如果从未被观察到,则为0)。
我写的函数运行良好,在小数据集上做了它应该做的事情。但是,当使用像选票这样的大数据集时,R崩溃了。所以我问是否存在一个更高效的函数,我可以使用,我如何提高效率?
谢谢!

shyt4zoc

shyt4zoc1#

我不太清楚为什么要使用因子,但这样的方法可行吗?

library(dplyr)
library(tidyr)
datafreq <- function(dati){
  dati <- na.omit(dati)
  dati %>%
    count(across(everything()), name = "y") %>%
    complete(!!!syms(setdiff(names(dati), "y")),
             fill = list(y = 0))
    
}

**编辑:**更新答案以反映OP的更新问题。

我不确定这是否能实现您所期望的效率,但您可以使用的一些函数是expand.grid()data.table::CJ()tidyr::expand(),它们都完成相同的任务,即创建数据中所有组合的扩展 Dataframe 。
一种可能的解决方案可能是对现有组合进行计数,展开所有组合并加入计数。

DPLYR/TIDYR

library(dplyr)
library(tidyr)
datafreq <- function(dati){
  dati %>%
    # Remove NA
    drop_na() %>%
    # COUNT
    count(across(everything()), name = "y") %>%
    # EXPAND AND FULL JOIN
    complete(!!!syms(setdiff(names(dati), "y")),
             fill = list(y = 0))
}
out <- df %>%
  select(-republican) %>%
  datafreq()

数据表

或者,这里有一个data.table解决方案

library(data.table)
datafreq2 <- function(dati){
  # Coerce to DT
  dati <- as.data.table(dati)
  # Remove NAs
  dati <- na.omit(dati) 
  # COUNT
  counts <- dati[, list(y = .N), by = names(dati)]
  # EXPAND
  out <- do.call(get("CJ", asNamespace("data.table")),
                 args = c(dati, sorted = TRUE, unique = TRUE))
  # FULL-JOIN
  out <- merge(counts, out,
               all = TRUE, 
               by = names(out), sort = FALSE)
  # REPLACE NA counts with 0
  setnafill(out, type = "const", fill = 0, cols = "y")
  out
}
df <- as.data.table(df)
out <- datafreq2(df[, .SD, .SDcols = setdiff(names(df), "republican")])
vuv7lop3

vuv7lop32#

使用data.table

library(data.table)

dt <- fread("C:/temp/house-votes-84.data", header = FALSE)
u <- lapply(dt, unique)
a <- rev(cumprod(c(1, rev(lengths(u)[-1]))))
dt2 <- do.call(CJ, lapply(lengths(u), seq.int))
dt2[,counts := tabulate(colSums(t(mapply(function(i) match(dt[[i]], u[[i]]), seq_along(dt)) - 1)*a) + 1, .N)]
nrow(dt) == sum(dt2$counts)
#> [1] TRUE

dt中的值是u中的值的索引,因此dt2[i, j]对应于u[[j]][dt2[i, j]]

相关问题