按组计算平均值

2023-12-01

我有一个类似于此的大型数据框:

df <- data.frame(dive = factor(sample(c("dive1","dive2"), 10, replace=TRUE)),
                 speed = runif(10)
                 )
> df
    dive      speed
1  dive1 0.80668490
2  dive1 0.53349584
3  dive2 0.07571784
4  dive2 0.39518628
5  dive1 0.84557955
6  dive1 0.69121443
7  dive1 0.38124950
8  dive2 0.22536126
9  dive1 0.04704750
10 dive2 0.93561651

我的目标是当另一列等于某个值时获得一列中值的平均值,并对所有值重复此操作。即在上面的示例中,我想返回该列的平均值speed对于列的每个唯一值dive。所以当dive==dive1,平均值为speed是这个等等对于每个值dive.


在 R 中,有很多方法可以做到这一点。具体来说,by, aggregate, split, and plyr, cast, tapply, data.table, dplyr,等等。

从广义上讲,这些问题的形式是拆分-应用-组合。哈德利·威克姆 (Hadley Wickham) 写过一篇漂亮的文章这将使您更深入地了解整个问题类别,非常值得一读。他的plyr包实现了通用数据结构的策略,并且dplyr是针对数据帧调整的较新的实现性能。它们允许解决相同形式但比这个问题更复杂的问题。作为解决数据操作问题的通用工具,它们非常值得学习。

性能是非常大的数据集上的一个问题,因此很难击败基于data.table。但是,如果您只处理中型或更小的数据集,请花时间学习data.table可能不值得付出努力。dplyr也可以很快,所以如果你想加快速度,但不太需要可扩展性,这是一个不错的选择data.table.

下面的许多其他解决方案不需要任何额外的包。其中一些在中型数据集上甚至相当快。它们的主要缺点是隐喻或灵活性。通过比喻,我的意思是,它是一种为其他事物而设计的工具,旨在以“聪明”的方式强制解决这种特定类型的问题。我所说的灵活性是指他们缺乏解决广泛的类似问题或轻松产生整洁输出的能力。


Examples

base功能

tapply:

tapply(df$speed, df$dive, mean)
#     dive1     dive2 
# 0.5419921 0.5103974

aggregate:

aggregate接收 data.frames,输出 data.frames,并使用公式接口。

aggregate( speed ~ dive, df, mean )
#    dive     speed
# 1 dive1 0.5790946
# 2 dive2 0.4864489

by:

在其最用户友好的形式中,它接收向量并对它们应用函数。然而,它的输出并不是一种非常易于操作的形式:

res.by <- by(df$speed, df$dive, mean)
res.by
# df$dive: dive1
# [1] 0.5790946
# ---------------------------------------
# df$dive: dive2
# [1] 0.4864489

为了解决这个问题,为了简单的使用by the as.data.frame方法中的taRifx图书馆作品:

library(taRifx)
as.data.frame(res.by)
#    IDX1     value
# 1 dive1 0.6736807
# 2 dive2 0.4051447

split:

顾名思义,它仅执行拆分-应用-组合策略的“拆分”部分。为了使剩下的工作顺利进行,我将编写一个使用以下函数的小函数sapply用于应用组合。sapply自动尽可能地简化结果。在我们的例子中,这意味着一个向量而不是一个 data.frame,因为我们只有一维的结果。

splitmean <- function(df) {
  s <- split( df, df$dive)
  sapply( s, function(x) mean(x$speed) )
}
splitmean(df)
#     dive1     dive2 
# 0.5790946 0.4864489 

外部封装

数据表:

library(data.table)
setDT(df)[ , .(mean_speed = mean(speed)), by = dive]
#    dive mean_speed
# 1: dive1  0.5419921
# 2: dive2  0.5103974

dplyr:

library(dplyr)
group_by(df, dive) %>% summarize(m = mean(speed))

plyr(前身为dplyr)

这是什么官方网站不得不说plyr:

已经可以做到这一点baseR 函数(如split和 这apply函数族),但是plyr让一切变得更容易 和:

  • 完全一致的名称、参数和输出
  • 通过方便的并行化foreach package
  • data.frames、矩阵和列表的输入和输出
  • 进度条用于跟踪长时间运行的操作
  • 内置错误恢复和信息丰富的错误消息
  • 在所有转换中维护的标签

换句话说,如果您学习一种用于拆分-应用-组合操作的工具,它应该是plyr.

library(plyr)
res.plyr <- ddply( df, .(dive), function(x) mean(x$speed) )
res.plyr
#    dive        V1
# 1 dive1 0.5790946
# 2 dive2 0.4864489

reshape2:

The reshape2库的设计并不是以拆分-应用-组合作为主要焦点。相反,它使用两部分熔化/铸造策略来执行m 各种各样的数据重塑任务。但是,由于它允许聚合函数,因此可以用于解决此问题。它不是我进行分割-应用-组合操作的首选,但它的重塑功能很强大,因此你也应该学习这个包。

library(reshape2)
dcast( melt(df), variable ~ dive, mean)
# Using dive as id variables
#   variable     dive1     dive2
# 1    speed 0.5790946 0.4864489

基准测试

10行2组

library(microbenchmark)
m1 <- microbenchmark(
  by( df$speed, df$dive, mean),
  aggregate( speed ~ dive, df, mean ),
  splitmean(df),
  ddply( df, .(dive), function(x) mean(x$speed) ),
  dcast( melt(df), variable ~ dive, mean),
  dt[, mean(speed), by = dive],
  summarize( group_by(df, dive), m = mean(speed) ),
  summarize( group_by(dt, dive), m = mean(speed) )
)

> print(m1, signif = 3)
Unit: microseconds
                                           expr  min   lq   mean median   uq  max neval      cld
                    by(df$speed, df$dive, mean)  302  325  343.9    342  362  396   100  b      
              aggregate(speed ~ dive, df, mean)  904  966 1012.1   1020 1060 1130   100     e   
                                  splitmean(df)  191  206  249.9    220  232 1670   100 a       
  ddply(df, .(dive), function(x) mean(x$speed)) 1220 1310 1358.1   1340 1380 2740   100      f  
         dcast(melt(df), variable ~ dive, mean) 2150 2330 2440.7   2430 2490 4010   100        h
                   dt[, mean(speed), by = dive]  599  629  667.1    659  704  771   100   c     
 summarize(group_by(df, dive), m = mean(speed))  663  710  774.6    744  782 2140   100    d    
 summarize(group_by(dt, dive), m = mean(speed)) 1860 1960 2051.0   2020 2090 3430   100       g 

autoplot(m1)

benchmark 10 rows

照常,data.table开销稍多一些,因此对于小数据集来说大约是平均水平。不过,这些都是微秒,因此差异微不足道。任何方法在这里都可以正常工作,您应该根据以下因素进行选择:

  • 您已经熟悉或想要熟悉的内容(plyr其灵活性始终值得学习;data.table如果您打算分析庞大的数据集,那么值得学习;by and aggregate and split都是基本 R 函数,因此普遍可用)
  • 它返回什么输出(数字、data.frame 或 data.table ——后者继承自 data.frame)

1000万行,10组

但是如果我们有一个大数据集怎么办?让我们尝试将 10^7 行分为十组。

df <- data.frame(dive=factor(sample(letters[1:10],10^7,replace=TRUE)),speed=runif(10^7))
dt <- data.table(df)
setkey(dt,dive)

m2 <- microbenchmark(
  by( df$speed, df$dive, mean),
  aggregate( speed ~ dive, df, mean ),
  splitmean(df),
  ddply( df, .(dive), function(x) mean(x$speed) ),
  dcast( melt(df), variable ~ dive, mean),
  dt[,mean(speed),by=dive],
  times=2
)

> print(m2, signif = 3)
Unit: milliseconds
                                           expr   min    lq    mean median    uq   max neval      cld
                    by(df$speed, df$dive, mean)   720   770   799.1    791   816   958   100    d    
              aggregate(speed ~ dive, df, mean) 10900 11000 11027.0  11000 11100 11300   100        h
                                  splitmean(df)   974  1040  1074.1   1060  1100  1280   100     e   
  ddply(df, .(dive), function(x) mean(x$speed))  1050  1080  1110.4   1100  1130  1260   100      f  
         dcast(melt(df), variable ~ dive, mean)  2360  2450  2492.8   2490  2520  2620   100       g 
                   dt[, mean(speed), by = dive]   119   120   126.2    120   122   212   100 a       
 summarize(group_by(df, dive), m = mean(speed))   517   521   531.0    522   532   620   100   c     
 summarize(group_by(dt, dive), m = mean(speed))   154   155   174.0    156   189   321   100  b      

autoplot(m2)

benchmark 1e7 rows, 10 groups

Then data.table or dplyr使用操作于data.tables 显然是要走的路。某些方法(aggregate and dcast)开始看起来很慢。

1000万行,1000组

如果你有更多的组,差异就会变得更加明显。和1,000组和相同的 10^7 行:

df <- data.frame(dive=factor(sample(seq(1000),10^7,replace=TRUE)),speed=runif(10^7))
dt <- data.table(df)
setkey(dt,dive)

# then run the same microbenchmark as above
print(m3, signif = 3)
Unit: milliseconds
                                           expr   min    lq    mean median    uq   max neval    cld
                    by(df$speed, df$dive, mean)   776   791   816.2    810   828   925   100  b    
              aggregate(speed ~ dive, df, mean) 11200 11400 11460.2  11400 11500 12000   100      f
                                  splitmean(df)  5940  6450  7562.4   7470  8370 11200   100     e 
  ddply(df, .(dive), function(x) mean(x$speed))  1220  1250  1279.1   1280  1300  1440   100   c   
         dcast(melt(df), variable ~ dive, mean)  2110  2190  2267.8   2250  2290  2750   100    d  
                   dt[, mean(speed), by = dive]   110   111   113.5    111   113   143   100 a     
 summarize(group_by(df, dive), m = mean(speed))   625   630   637.1    633   644   701   100  b    
 summarize(group_by(dt, dive), m = mean(speed))   129   130   137.3    131   142   213   100 a     

autoplot(m3)

enter image description here

So data.table继续良好地扩展,并且dplyr操作于data.table也运作良好,与dplyr on data.frame慢了接近一个数量级。这split/sapply该策略似乎在组数量方面扩展不佳(意味着split()可能很慢并且sapply速度很快)。by仍然相对高效——5秒,这对用户来说绝对是明显的,但对于这么大的数据集来说仍然不是不合理的。不过,如果您经常处理这种大小的数据集,data.table显然是要走的路 - 100% data.table 以获得最佳性能或dplyr with dplyr using data.table作为一个可行的替代方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

按组计算平均值 的相关文章

  • 尝试读取 CSV 文件时出现“无法识别的字符串转义”

    我正在尝试导入一个 csv文件 以便我可以观看此视频 R ggplot2 图形直方图 http www youtube com watch v 47kWynt3b6M 我安装了所有正确的软件包 包括ggplot以及相关的包 视频中的第一个说
  • API 请求和curl::curl_fetch_memory(url, handle = handle) 中的错误:SSL 证书问题:证书已过期

    几天前 我运行了代码几个月 没有任何问题 GET url myurl query 今天我遇到一个错误 Error in curl curl fetch memory url handle handle SSL certificate pro
  • 在 R 中创建虚拟变量,排除某些情况为 NA

    我的数据看起来像这样 V1 V2 A 0 B 1 C 2 D 3 E 4 F 5 G 9 我想创建一个虚拟变量R where 0 1 1 2 3 4 and NA 0 5 9 应该很简单 有人可以帮忙吗 我们可以转换V2 into a fa
  • Purrr::map_df() 删除 NULL 行

    使用时purrr map df 我偶尔会传递一个数据框列表 其中一些项目是NULL 当我做 map df 返回行数少于原始列表的数据框 我想发生的事情是这样的map df calls dplyr bind rows 它忽略了NULL价值观
  • R 中的列乘以子字符串

    假设我有一个数据框 其中包含多个组件及其在多个列中列出的属性 并且我想对这些列运行多个函数 我的方法是尝试将其基于每个列标题中的子字符串 但我无法弄清楚如何做到这一点 下面是数据框的示例 Basket F Type 1 F Qty 1 F
  • 将每列的值乘以 R 中另一个 data.frame 中的权重

    我有两个data frames df and weights 代码如下 df看起来像这样 id a b d EE f 1 this 0 23421153 0 02324956 0 5457353 0 73068586 0 5642554 2
  • ggplot2 geom_密度和geom_histogram在一个图中

    如何制作一个所有条形加起来为 1 的直方图 并在适合的上方添加一个密度层 set seed 1234 df lt data frame sex factor rep c F M each 200 weight round c rnorm 2
  • 使用 Shiny 发布平行坐标图表时出现“错误:路径[1]="”:没有这样的文件或目录”

    我有一个似乎很常见但我还没有找到解决方案的问题 当尝试使用 rCharts Parcoords 发布 Web 应用程序时 出现以下错误 错误 路径 1 没有这样的文件或目录 奇怪的是 该应用程序在我的笔记本电脑上运行得很好 下面是我正在使用
  • 在 Pandas DataFrame Python 中添加新列[重复]

    这个问题在这里已经有答案了 例如 我在 Pandas 中有数据框 Col1 Col2 A 1 B 2 C 3 现在 如果我想再添加一个名为 Col3 的列 并且该值基于 Col2 式中 如果Col2 gt 1 则Col3为0 否则为1 所以
  • 使用基于正则表达式的部分匹配来选择 Pandas 数据帧的子数据帧

    我有一个 Pandas 数据框 它有两列 一列 进程参数 列 包含字符串 另一列 值 列 包含相应的浮点值 我需要过滤出部分匹配列 过程参数 中的一组键的子数据帧 并提取与这些键匹配的数据帧的两列 df pd DataFrame Proce
  • Pandas 与 Numpy 数据帧

    看这几行代码 df2 df copy df2 1 df 1 df 1 values 1 df2 ix 0 0 我们的教练说我们需要使用 values属性来访问底层的 numpy 数组 否则我们的代码将无法工作 我知道 pandas Data
  • 计算 R 中各列的唯一值

    我正在尝试创建一个新变量 其中包含来自两个不同列的字符串值的唯一计数 所以我有这样的东西 例如 A tibble 4 x 2 names partners
  • 如何在 R 或 Python 中制作旭日图?

    到目前为止 我一直无法找到一个可以创建旭日图的 R 库约翰 斯塔斯科 http www cc gatech edu gvu ii sunburst 有人知道如何在 R 或 Python 中实现这一点吗 在极坐标投影中使用 matplotli
  • 所有 x 轴标签未以 45 度显示

    I m having the code as like below But I m not getting all the x axis labels and it is not displaying in 45 degree when I
  • 使用 ggmap 截断密度多边形

    我在使用 R ggmap 绘制密度图时遇到问题 我的数据如下所示 gt head W date lat lon dist 1 2010 01 01 31 942 86 659 292 415 2 2010 01 10 32 970 84 1
  • 跨行对 Pandas 数据框进行分组 - 2.0

    进一步这个问题跨行对 Pandas 数据框进行分组 https stackoverflow com questions 46995997 grouping pandas dataframe across rows 操作是 amount cl
  • 投资决策:R中的NPV、IRR、PB计算

    我正在尝试计算不同数量项目的净现值 NPV 内部收益率 IRR 和投资回收期 PB 时间 以评估哪个投资项目提供最佳回报 到目前为止 我可以为每个项目单独计算几行代码 但我想做的是 编写一个函数 它接受一个包含许多不同项目及其现金流的矩阵
  • 如何从 R 读取 PDF 元数据

    我们很好奇 有没有一种方法可以从 R 读取 PDF 元数据 例如下面显示的信息 通过搜索我对此无能为力 r pdf metadata在当前的问题库中 非常欢迎任何指点 我想不出纯 R 的方法来执行此操作 但您可能可以安装您最喜欢的 PDF
  • 闭包作为数据合并习惯的解决方案

    我正在尝试解决闭包问题 而且我think我发现了一个案例 他们可能会有所帮助 我有以下几部分需要处理 一组正则表达式 旨在清理状态名称 位于函数中 具有州名称 上述函数创建的标准化形式 和州 ID 代码的 data frame 用于链接两者
  • 线性判别分析图

    如何将样本 ID 行号 作为标签添加到此 LDA 图中的每个点 library MASS ldaobject lt lda Species data iris plot ldaobject panel function x y points

随机推荐

  • 尝试使用 Swift AVPlayer 播放音频

    这是我当前的视图控制器 import UIKit import AVFoundation class SecondViewController UIViewController override func viewDidLoad var p
  • 重叠的 AWT 线和 Swing JLabels

    我在使用线基元的应用程序中遇到问题JLables 我尝试解释一下 我必须使用线条来代表道路来绘制车辆路线JLabels来代表城市 我需要使用JLabels因为每个 JLabel 都有一个监听器 用于显示包含城市信息的对话框 我重新定义pai
  • 如果返回值被忽略,如何发出警告?

    我想查看我的代码 C 中忽略函数返回值的所有位置 我怎样才能做到这一点 使用 gcc 或静态代码分析工具 错误代码示例 int f int z return z z 2 z 3 z z 23 int main int i 7 f i lt
  • Ajax 会话丢失

    我将 Symfony 应用程序从 Symfony 4 0 7 升级到 Symfony 4 1 之后 AJAX 调用会丢失会话值 我同时调用了大约 6 个 ajax 请求 第一个进展顺利 但其他人正在失去会话值 它仅在迁移到 Symfony
  • 用golang封装一个包

    想象一个导出一些结构和一些函数的包 如果我想围绕该包制作一个包装器 以便它可以用作插件 我是否应该重新创建嵌入旧结构的结构 例子 package foo type Foo struct Field string func DoSomethi
  • Google Fit API 配额和限制

    使用 google fit api 时是否有配额和请求限制 我想使用 google fit api 我很好奇使用它时是否有限制 您可以在以下位置检查您项目的 Fitness API 当前限制谷歌开发者控制台 我检查了当前的项目 默认限制是
  • Python - SqlAlchemy:按大圆距离过滤查询?

    我正在使用 Python 和 Sqlalchemy 在 Sqlite 数据库中存储纬度和经度值 我创建了一个混合法对于我的位置对象 hybrid method def great circle distance self other Tri
  • 导入变量命名空间

    是否可以使用这样的变量导入名称空间 namespace User Authorization Certificate use namespace 显然这不会运行use声明需要一个常量 但有解决方法吗 Edit 发现了一个 gem 仅适用于
  • Liferay 7 主题中的 jQuery 插件

    我需要一些帮助来理解 Liferay 7 主题 特别是使用 jQuery 插件 因为我遇到了与此线程相同的问题 https web liferay com community forums message boards view messa
  • 由于嵌套节点依赖关系,路径太长

    我正在使用 npm 来安装依赖项 安装完这些后 我想与非技术人员共享我的项目 并且没有 npm 所以我想在应用程序内发送 node modules 但是 由于节点嵌套了依赖项 因此它创建的文件具有很长的路径 217 个字符 node mod
  • 为什么 iTextSharp 中的 GetTextFromPage 返回的字符串越来越长?

    我正在使用最新的iTextSharpnuGet 5 5 8 中的 lib 用于解析 pdf 文件中的一些文本 我面临的问题是GetTextFromPage方法不仅返回应有的页面文本 还返回上一页的文本 这是我的代码 var url http
  • 通过 C# 代码执行 Powershell 命令

    我想通过 C 代码添加 Powershell 命令或脚本 什么是正确的 变量声明 默认值存储在 C 变量中 例如 在 Powershell 中我输入以下行 user Admin 我想在 C 代码中添加这一行 powershell AddSc
  • 在 Ubuntu 20.04 上安装 MySQL 时出现问题

    我正在尝试在 Ubuntu 20 04 中安装 MySQL 8 0sudo apt install mysql server 但是重新安装和使用后仍然出现此错误sudo dpkg configure a Setting up mysql s
  • 如何为一个类实例化更多 CDI bean?

    Note 类似的问题已经在三年前被问过 在 EE 6 的时候 请参阅如何为一个类实例化多个 CDI Weld bean 有什么变化吗EE 7 在 Spring 中 可以通过在 xml conf 中定义相应的 bean 来实例化任何类 也可以
  • PhoneGap 启动图片 iOS Apple Store 提交 [重复]

    这个问题在这里已经有答案了 一如既往地提交iTunesConnect of my PhoneGap申请起来比较麻烦 特别是当我尝试使用时 我看到弹出这条新消息Application Loader Your binary is not opt
  • 面向对象编程。从方法内部调用方法

    如何从类内的函数调用类方法 我的代码是 var myExtension init function Call onPageLoad onPageLoad function Do something 我试过了 onPageLoad 来自 in
  • 如何在Vue Material中设置灵活的网格

    我正在尝试构建一个使用 Vue Material 在网格中渲染用户输入的卡片的界面 卡片正确渲染 然而 我希望我的网格能够以消除间隙的方式弯曲 对齐和交错不同尺寸的卡片 如下所示 下面的代码与上面的网格相对应
  • PHP:使用来自 php 的参数调用 javascript 函数

    我正在尝试使用 PHP 变量参数调用 JavaScript 函数 我尝试了两种方法 在 PHP 中使用 echo 中的脚本标签调用 JavaScript 函数 IE 将 PHP 变量值赋给 JavaScript 变量
  • 为什么 Numba 不改进这个递归函数

    我有一个结构非常简单的真 假值数组 the real array has hundreds of thousands of items positions np array True False False False True True
  • 按组计算平均值

    我有一个类似于此的大型数据框 df lt data frame dive factor sample c dive1 dive2 10 replace TRUE speed runif 10 gt df dive speed 1 dive1