You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用更优的R方法按行函数扩展DataFrame?

问题:

以下代码可实现需求,但是否存在更符合“R风格”的方法?我需要根据自定义函数将分组数据拆分为单独行(目前使用循环实现)。

示例:
df1 <- data.frame(group = c("A", "B", "C"), 
              volume = c(200L, 45L, 104L)
              )
print(df1)
#>   group volume
#> 1     A    200
#> 2     B     45
#> 3     C    104

我希望按group将volume拆分为多行,最终得到的DataFrame中,新列vol2的总和等于原volume。本示例中使用除数52进行整数运算,预期结果如下:

print(df3)
#>    group vol2
#> 1      A   52
#> 2      A   52
#> 3      A   52
#> 4      A   44
#> 21     B   45
#> 31     C   52
#> 32     C   52
当前可行方案

以下代码可得到上述预期结果:

div <- 52L
df1$intgr <- df1$volume %/% div
df1$remainder <- df1$volume %% div

print(df1)
#>   group volume intgr remainder
#> 1     A    200     3        44
#> 2     B     45     0        45
#> 3     C    104     2         0

df2 <- data.frame()

for (r in 1:nrow(df1)){
  if(df1[r,"intgr"] > 0){
    for (k in 1:as.integer(df1[r,"intgr"])){
      df1[r,"vol2"] <- div
      df2 <- rbind(df2, df1[r,])
    }
  }
  if(df1[r,"remainder"]>0){
    df1[r, "vol2"] <- as.integer(df1[r, "remainder"])
    df2 <- rbind(df2, df1[r,])
  }
}

print(df2)
#>    group volume intgr remainder vol2
#> 1      A    200     3        44   52
#> 2      A    200     3        44   52
#> 3      A    200     3        44   52
#> 4      A    200     3        44   44
#> 21     B     45     0        45   45
#> 31     C    104     2         0   52
#> 32     C    104     2         0   52

df3 <- subset(df2, select = c("group", "vol2"))

print(df3)
#>    group vol2
#> 1      A   52
#> 2      A   52
#> 3      A   52
#> 4      A   44
#> 21     B   45
#> 31     C   52
#> 32     C   52

作为R新手,我想知道是否有更优的方法/函数实现该需求,比如通过应用自定义函数(UDF)处理DataFrame。此前搜索“expand group”多得到expand.grid,并非所需方案,期待建议!

更优的R风格实现方案

方案1:使用tidyverse生态(dplyr + tidyr)

利用管道操作和列表列展开,代码简洁易读,符合现代R的编程风格:

library(tidyverse)

div <- 52L

df3 <- df1 %>%
  mutate(
    intgr = volume %/% div,
    remainder = volume %% div,
    # 生成每个分组对应的vol2向量
    vol2 = map2(intgr, remainder, ~c(rep(div, .x), if(.y > 0) .y else NULL))
  ) %>%
  # 展开列表列
  unnest(vol2) %>%
  # 保留需要的列
  select(group, vol2)

print(df3)
#> # A tibble: 7 × 2
#>   group  vol2
#>   <chr> <int>
#> 1 A        52
#> 2 A        52
#> 3 A        52
#> 4 A        44
#> 5 B        45
#> 6 C        52
#> 7 C        52

方案2:使用base R

无需额外安装包,通过列表生成再合并的方式替代嵌套循环,避免频繁rbind带来的性能损耗:

div <- 52L
df1$intgr <- df1$volume %/% div
df1$remainder <- df1$volume %% div

# 遍历每一行生成对应的数据框
result_list <- lapply(1:nrow(df1), function(r) {
  group_val <- df1$group[r]
  # 构造vol2的数值向量
  vol_vals <- c(rep(div, df1$intgr[r]), if(df1$remainder[r] > 0) df1$remainder[r] else NULL)
  data.frame(group = group_val, vol2 = vol_vals)
})

# 合并所有结果
df3 <- do.call(rbind, result_list)

print(df3)
#>    group vol2
#> 1      A   52
#> 2      A   52
#> 3      A   52
#> 4      A   44
#> 5      B   45
#> 6      C   52
#> 7      C   52

内容的提问来源于stack exchange,提问作者ScottyJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 15:00:45