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

在R中按前缀分组DataFrame列并实现列求和的技术疑问

问题

我有一个包含二进制列的大型DataFrame,列名如下:

[1] "imagetag_logos_position_Apple_BOTTOM_CENTER"         "imagetag_logos_position_Apple_BOTTOM_LEFT"           "imagetag_logos_position_Apple_BOTTOM_RIGHT"          "imagetag_logos_position_Apple_CENTER"                "imagetag_logos_position_Apple_CENTER_LEFT"          
  [6] "imagetag_logos_position_Apple_CENTER_RIGHT"          "imagetag_logos_position_Apple_TOP_CENTER"            "imagetag_logos_position_Apple_TOP_LEFT"              "imagetag_logos_position_Apple_TOP_RIGHT"             "imagetag_logos_position_Banana_BOTTOM_CENTER"       
 [11] "imagetag_logos_position_Banana_BOTTOM_LEFT"          "imagetag_logos_position_Banana_BOTTOM_RIGHT"         "imagetag_logos_position_Banana_CENTER_LEFT"          "imagetag_logos_position_Banana_CENTER_RIGHT"         "imagetag_logos_position_Banana_TOP_RIGHT"           
 [16] "imagetag_logos_position_Pear_BOTTOM_CENTER"      "imagetag_logos_position_Pear_BOTTOM_LEFT"        "imagetag_logos_position_Pear_BOTTOM_RIGHT"       "imagetag_logos_position_Pear_CENTER"             "imagetag_logos_position_Pear_CENTER_LEFT"       
 [21] "imagetag_logos_position_Pear_CENTER_RIGHT"       "imagetag_logos_position_Pear_TOP_RIGHT"          "imagetag_logos_position_Kiwi_BOTTOM_CENTER"    "imagetag_logos_position_Kiwi_BOTTOM_LEFT"      "imagetag_logos_position_Kiwi_BOTTOM_RIGHT"    
 [26] "imagetag_logos_position_Kiwi_CENTER_LEFT"      "imagetag_logos_position_Kiwi_CENTER_RIGHT"     "imagetag_logos_position_Kiwi_TOP_LEFT"         "Product_position_Product_0"                         "Product_position_Product_BOTTOM_CENTER"            
 [31] "Product_position_Product_BOTTOM_LEFT"               "Product_position_Product_BOTTOM_RIGHT"              "Product_position_Product_CENTER"                    "Product_position_Product_CENTER_LEFT"               "Product_position_Product_CENTER_RIGHT"              
 [36] "Product_position_Product_TOP_CENTER"                "Product_position_Product_TOP_LEFT"                  "Product_position_Product_TOP_RIGHT"                 "Person_position_Person_0"                           "Person_position_Person_BOTTOM_CENTER"               
 [41] "Person_position_Person_BOTTOM_LEFT"                 "Person_position_Person_BOTTOM_RIGHT"                "Person_position_Person_CENTER"                      "Person_position_Person_CENTER_LEFT"                 "Person_position_Person_CENTER_RIGHT"               
 [46] "Person_position_Person_TOP_CENTER"                  "Person_position_Person_TOP_LEFT"                    "Person_position_Person_TOP_RIGHT"                   "Logo_position_Logo_0"                               "Logo_position_Logo_BOTTOM_CENTER"                  
 [51] "Logo_position_Logo_BOTTOM_LEFT"                     "Logo_position_Logo_BOTTOM_RIGHT"                    "Logo_position_Logo_CENTER"                          "Logo_position_Logo_CENTER_LEFT"                     "Logo_position_Logo_CENTER_RIGHT"                    
 [56] "Logo_position_Logo_TOP_CENTER"                      "Logo_position_Logo_TOP_LEFT"                        "Logo_position_Logo_TOP_RIGHT"                       "CTA_ShopNow_position_Shop Now_0"                    "CTA_ShopNow_position_Shop Now_BOTTOM_CENTER"       
 [61] "CTA_ShopNow_position_Shop Now_BOTTOM_LEFT"          "CTA_ShopNow_position_Shop Now_BOTTOM_RIGHT"         "CTA_ShopNow_position_Shop Now_CENTER"               "CTA_ShopNow_position_Shop Now_CENTER_LEFT"          "CTA_ShopNow_position_Shop Now_CENTER_RIGHT"        
 [66] "CTA_ShopNow_position_Shop Now_TOP_CENTER"           "CTA_ShopNow_position_Shop Now_TOP_RIGHT"            "CTA_JoinNow_position_Join Now_0"                    "CTA_JoinNow_position_Join Now_BOTTOM_CENTER"        "CTA_JoinNow_position_Join Now_BOTTOM_LEFT"         
 [71] "CTA_JoinNow_position_Join Now_BOTTOM_RIGHT"         "CTA_JoinNow_position_Join Now_CENTER"               "CTA_JoinNow_position_Join Now_CENTER_RIGHT"         "CTA_JoinNow_position_Join Now_TOP_CENTER"           "CTA_JoinNow_position_Join Now_TOP_RIGHT"           
 [76] "CTA_position_CTA_0"                                 "CTA_position_CTA_BOTTOM_CENTER"                     "CTA_position_CTA_BOTTOM_LEFT"                       "CTA_position_CTA_BOTTOM_RIGHT"                      "CTA_position_CTA_CENTER"                            
 [81] "CTA_position_CTA_CENTER_LEFT"                       "CTA_position_CTA_CENTER_RIGHT"                      "CTA_position_CTA_TOP_CENTER"                        "CTA_position_CTA_TOP_LEFT"                          "CTA_position_CTA_TOP_RIGHT"                         
 [86] "Text_position_text_BOTTOM_CENTER"                   "Text_position_text_BOTTOM_LEFT"                     "Text_position_text_BOTTOM_RIGHT"                    "Text_position_text_CENTER"                          "Text_position_text_CENTER_LEFT"                     
 [91] "Text_position_text_CENTER_RIGHT"                    "Text_position_text_TOP_CENTER"                      "Text_position_text_TOP_LEFT"                        "Text_position_text_TOP_RIGHT"                       "Product_position_Product_0_LF"                      
 [96] "Product_position_Product_BOTTOM_CENTER_LF"          "Product_position_Product_BOTTOM_LEFT_LF"            "Product_position_Product_BOTTOM_RIGHT_LF"           "Product_position_Product_CENTER_LF"                 "Product_position_Product_CENTER_LEFT_LF"           
[101] "Product_position_Product_CENTER_RIGHT_LF"           "Product_position_Product_TOP_CENTER_LF"             "Product_position_Product_TOP_LEFT_LF"               "Product_position_Product_TOP_RIGHT_LF"              "Logo_position_Logo_0_LF"                           

我需要按前缀分组,对每组中包含BOTTOM_CENTER、BOTTOM_RIGHT、BOTTOM_LEFT的列求和。比如imagetag_logos_position_Apple_相关的底部位置列单独求和,imagetag_logos_position_Banana_的相关列也单独求和。

我已经用以下代码提取了唯一前缀列表:

library(stringr)
prefix_list <- str_extract(colnames(positionsdf),".+?(?=([A-Z])([A-Z])([A-Z]))")
prefix_list1 <- unique(prefix_list)

得到的唯一前缀列表:

> prefix_list1
 [1] "imagetag_logos_position_Apple_"      "imagetag_logos_position_Banana_"     "imagetag_logos_position_Kiwi_"   "imagetag_logos_position_Pear_" NA                                   "Product_position_Product_"          "Person_position_Person_"           
 [8] "Logo_position_Logo_"                "CTA_ShopNow_position_Shop Now_"     "CTA_JoinNow_position_Join Now_"     "CTA_position_"                      "Text_position_text_"                "CTA_LearnMore_position_Learn More_" "Person_position_"  

尝试过用%in%匹配,但它不支持部分匹配,循环代码也没成功:

for(i in prefix_list1){
  sapply(positionsdf, function(x) i %in% x)
}

现在需要找到合适的方法实现按前缀分组求和。


解决方案

方法1:grepl匹配前缀 + 循环求和

用grepl实现部分匹配,筛选对应列后计算每行求和,最后合并结果:

library(dplyr)

# 过滤前缀列表中的NA值
valid_prefixes <- prefix_list1[!is.na(prefix_list1)]

# 初始化结果DataFrame
result_df <- data.frame()

for(prefix in valid_prefixes){
  # 筛选当前前缀下的底部位置列
  target_cols <- colnames(positionsdf)[
    grepl(paste0("^", prefix), colnames(positionsdf)) & 
    grepl("BOTTOM_(CENTER|LEFT|RIGHT)", colnames(positionsdf))
  ]
  
  # 存在符合条件的列时计算求和
  if(length(target_cols) > 0){
    sum_col <- rowSums(positionsdf[target_cols])
    # 生成新列名(去掉前缀末尾下划线,添加标识)
    col_name <- gsub("_$", "", prefix) |> paste0("_bottom_sum")
    result_df[[col_name]] <- sum_col
  }
}

# 将求和结果合并到原DataFrame(可选)
positionsdf <- cbind(positionsdf, result_df)

方法2:dplyr的across + matches批量处理

用dplyr的语法实现更简洁的批量求和:

library(dplyr)
library(stringr)

valid_prefixes <- prefix_list1[!is.na(prefix_list1)]

positionsdf <- positionsdf |> 
  mutate(
    !!!setNames(
      lapply(valid_prefixes, function(prefix){
        # 生成匹配规则
        matches_pattern <- paste0("^", prefix, "BOTTOM_(CENTER|LEFT|RIGHT)")
        rowSums(across(matches(matches_pattern)))
      }),
      # 生成新列名
      gsub("_$", "", valid_prefixes) |> paste0("_bottom_sum")
    )
  )

方法3:purrr函数式处理

用purrr的map替代循环,代码更简洁:

library(purrr)
library(dplyr)
library(stringr)

valid_prefixes <- prefix_list1[!is.na(prefix_list1)]

# 定义单前缀求和函数
sum_bottom_cols <- function(prefix){
  pattern <- paste0("^", prefix, "BOTTOM_(CENTER|LEFT|RIGHT)")
  cols <- matches(pattern)
  if(any(colnames(positionsdf) %in% cols)){
    rowSums(across(cols))
  } else {
    NULL
  }
}

# 生成所有求和列并合并
bottom_sums <- map_dfc(valid_prefixes, sum_bottom_cols)
colnames(bottom_sums) <- gsub("_$", "", valid_prefixes) |> paste0("_bottom_sum")

# 合并到原DataFrame
positionsdf <- bind_cols(positionsdf, bottom_sums)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:15:34