在 R 中,为什么使用 dplyr 的操作根据数据帧的格式(长与宽)花费不同的时间?

问题描述 投票:0回答:1

我注意到,根据数据集具有的变量/特征的数量,首先使用pivot_wider(更少的变量)或pivot_longer(更多的变量)可能会更快。我想知道这主要是因为什么?我的猜测是分组操作(更长的格式)和绑定(更宽的格式)之间的权衡,但我想知道是否有人有更多的见解。下面的示例将不同组的幂提高到随机值:

代码(很多功能):

# 5000 features , 100 observations

df_long = data.frame(grp=rep(1:100, each=5e3),
                     feat=paste0("V",rep(1:5e3, times=100)), 
                     val=rnorm(5e5))

df_wide = df_long %>% group_by(feat) %>% 
  pivot_wider(names_from = feat, 
              values_from = val) %>% ungroup()

system.time({
  df_long %>% 
    group_by(grp) %>% mutate(val=grp^val) 
})

system.time({
  df_wide %>% mutate(across(paste0("V",1:5000), ~grp^.))
})

结果:

   user  system elapsed 
  0.028   0.000   0.028 

   user  system elapsed 
  0.158   0.000   0.158

代码(较少功能):

# 100 features , 5000 observations

df_long = data.frame(grp=rep(1:5e3, each=100),
                     feat=paste0("V",rep(1:100, times=5e3)), 
                     val=rnorm(5e5))

df_wide = df_long %>% group_by(feat) %>% 
  pivot_wider(names_from = feat, 
              values_from = val) %>% ungroup()

system.time({
  df_long %>% 
    group_by(grp) %>% mutate(val=grp^val) 
})

system.time({
  df_wide %>% mutate(across(paste0("V",1:100), ~grp^.))
})

结果:

   user  system elapsed 
  0.051   0.000   0.050 

  user  system elapsed 
 0.025   0.000   0.025 
r performance runtime
1个回答
0
投票

比较不同尺寸的长格式,然后比较不同尺寸的宽格式可能会更容易。

对于长格式,具有 5000 个观测值的格式需要更长的时间,因为

group_by()
中有更多组。更多的组意味着他们需要更多次地进行相同的计算。这就是为什么
rowwise()
很强大,但通常是速度性能的瓶颈。 here提到了 dplyr 中的分组机制:

dplyr 是 Split-Apply-Combine 计算范式的有效实现。数据被分成组,然后将这些数据块传递给执行计算的函数,最后重新组合以生成聚合的数据帧。这种作案手法在 dplyr 的分组机制中很明显。当 data.frame 通过 group_by 传递时,会附加一个“groups”属性。

该对象是一个 data.frame,给出唯一的组,并且在第三(最后)列向量中包含属于该组的行的索引。像 summarise 这样的命令使用此信息将 data.frame 分成组,然后按顺序传递给所使用的函数,然后重新组合。这些步骤也是用 C++ 完成的,这使得 dplyr 非常高效。

对于宽格式,主要区别在于列数。速度差异来自于 R 中的数据帧是基于列的,这意味着它是按列存储的。因此,矢量化在这种情况下不起作用。

要点是列和组更少,速度更快。

© www.soinside.com 2019 - 2024. All rights reserved.