通过 sapply 维护 tapply 索引

Posted

技术标签:

【中文标题】通过 sapply 维护 tapply 索引【英文标题】:Maintain tapply indices through sapply 【发布时间】:2019-01-08 03:59:52 【问题描述】:

使用 tapply 和 sapply,我正在尝试根据我使用 sapply 提供给 tapply 的多个(两个)索引来求和计数。问题是返回的矩阵丢失了我给 tapply 的列名。我最终使用 melt() 将矩阵转换为 data.frame 以输入到 ggplot 中,并且必须以更手动的方式添加变量名称,但我希望它们仅通过两个 apply() 函数保留。当我仅在 tapply() 中的索引上使用时,度量/变量名称会被保留​​,所以我不知道为什么它们会因两个索引而丢失。

    Fc_desc. <- rep(c(rep("Local",10),rep("Collector",10),rep("Arterial",10)),2)
Year. <- c(rep(seq(2000,2008,2),12))
df.. <- data.frame(Fc_desc = Fc_desc., Year = Year., Tot_ped_fatal_cnt = sample(length(Year.)),Tot_ped_inj_lvl_a_cnt = sample(length(Year.)))
#Define metrics(columns) of interest
Metrics. <- c("Tot_ped_fatal_cnt", "Tot_ped_inj_lvl_a_cnt")
#Summarize into long data frame
Ped_FcSv.. <- melt(sapply(Metrics., function(x)tapply(df..[,x],list(df..$Year, df..$Fc_desc), sum,na.rm=T)),varnames = c("Fc_desc","Year","Injury_Severity"), value.name = "Count")

【问题讨论】:

不需要tapplysapply,试试这个:aggregate(.~Fc_desc + Year, data = df.., FUN = sum) 嗨 bouncyball - 但我需要指定数据框中的列来求和?在示例中,除了我的索引(Fc_desc 和 Year)之外,我只有 2 列,但在我的实际数据集中,我有 149 列我不感兴趣。我当然可以子集,但这似乎很乱。我还需要将生成的数据框转置为易于使用的 ggplot() -ing。如果我融化了你的结果,我会在我的 Metrics 列上堆叠 Year 列。 你在总结之前把事情变成长格式怎么样?喜欢df_long = reshape2::melt(df.., measure.vars = Metrics.)。然后,您可以在三个分组变量aggregate(value ~ Fc_desc + Year + variable, data = df_long, FUN = sum) 上仅聚合您关心的单个变量。 @aosmith - 这确实有效,但是当我应用melt() 时我必须对我的数据进行子集化,因为我的实际数据框有更多的数据列会影响该功能。我利用您的示例在上面的代码部分添加了一些代码并进行了必要的更改 您的意思是它会使事情变慢,或者列组合没有唯一值?我上面给出的代码适用于其他列...也许添加一个更像您的实际示例的示例,它具有额外的列,可以将扳手扔进东西。如果 melt()/-aggregate() 方法不起作用,我可能会切换到你最喜欢的附加包来解决这类数据操作问题(我通常使用 dplyr 【参考方案1】:

我最初的解决方案是使用循环和列表“

Metrics. <- c("Tot_ped_fatal_cnt", "Tot_ped_inj_lvl_a_cnt")
TempList_ <- list()
for(metric in Metrics.)
    TempList_[[metric]] <- tapply(df..[,metric],list(df..$Year, df..$Fc_desc),      
       sum) 

TempList_YrSv <- melt(TempList_, varnames = c("Year","Fc_desc"), value.name = 
    "Count")
colnames(TempList_YrSv )[3] <- "Injury_Severity"

我的 717,000 行实际数据使用 6 行代码,耗时 0.46 秒

我修改并应用了Aosmith解决方案:

Cols. <- c(Metrics., "Year","Fc_desc")
#Transpose data to long form
df_long <- melt(df..[,Cols.], measure.vars = Metrics., variable.name = c("Injury_Severity"), value.name = "Count")
#Apply aggregate() to sum Count on 3 indices
Ped_YrSv.. <- aggregate(Count ~ Fc_desc + Year + Injury_Severity, data = df_long, FUN = sum,na.rm=T)

这个解决方案需要 3.9 秒,但只有 3 行。我意识到分裂头发,但我试图变得更优雅,远离列表和循环,所以这很有帮助。我想我可以对此感到满意。谢谢大家。

【讨论】:

以上是关于通过 sapply 维护 tapply 索引的主要内容,如果未能解决你的问题,请参考以下文章

R中的高效批量处理函数(lapply sapply apply tapply mapply)(转)

R函数之:apply(), lapply(), sapply(), tapply()

R语言apply函数详解及实战(lapply, sapply, vapply, tapply,mapply)

r语言apply函数与tapply函数有啥区别

在 R 中使用 sapply 函数时,如何维护小标题的名称列表?

tapply 为因子索引的每个级别返回 NA 或坚持对象和索引的长度不同