R语言tidyverse:处理asfr列并保留指定列的技术问题
问题描述
我有一个包含超过50万条记录的数据集,示例结构如下:
library(tidyverse) sample <- tibble( iD=c(1,2), age=c(38,40), born_1=c(14,1),born_2=c(9,NA), born_3=c(4,NA), born_4=c(0,NA), asfr15=c( 0.0000), asfr16=c( 7.40444, 7.40444), asfr17=c( 42.87749, 7.40444), asfr18=c(73.05321, 7.40444),asfr19=c(98.28869, 7.40444),asfr20=c( 144.9568, 7.40444),asfr21= c (164.976,180.280),asfr22=c(180.280,180.280),asfr23=c(191.304,180.280),asfr24=c(200.199,180.280),asfr25=c(200.2018,180.280), asfr26=c(200.2007,180.280),asfr27=c( 200.3920,180.280),asfr28=c(197.6840,180.280),asfr29=c( 193.7632,180.280), asfr30=c(187.6072,180.280),asfr31=c(179.5616,180.280),asfr32=c( 170.5096,180.280),asfr33=c( 160.8376,180.280),asfr34=c( 150.4840,180.280),asfr35=c( 139.3304,180.280),asfr36=c( 127.7960,180.280),asfr37=c( 115.0280,180.280),asfr38=c( 100.7200,180.280), asfr39=c(85.6256,180.280),asfr40=c( 182.4384,180.280),asfr41=c( 178.412,180.280),asfr42=c( 171.928,180.280), asfr43=c( 163.316,180.280),asfr44=c( 152.9056,180.280),asfr45=c( 141.0264,180.280),asfr46=c( 128.008,180.280),asfr47=c( 114.180,180.280),asfr48=c( 99.872,180.280), asfr49=c( 85.4136,180.280))
我需要完成两个计算:
- 将
asfr15到asfr49列的值除以1000后求和,得到TFR列 - 将
asfr15到asfr49列的值除以1000后,再除以对应的TFR值,同时保留原始的iD、age、born_1到born_4列,并且asfr15到asfr49的列名保持不变
之前写的代码能完成计算,但会丢失需要保留的列:
sample3<- mutate(sample2, TFR=(rowSums(sample2[,7:41]))/1000) sample4<-((sample3[,2:36])/1000) / sample3[,49]
解决方案
方法1:使用tidyverse的across函数(推荐)
利用dplyr的across可以精准匹配目标列,在保留所有原始列的同时完成计算,步骤如下:
library(tidyverse) sample_processed <- sample %>% mutate( # 计算asfr系列列除以1000后的行和,生成TFR列 TFR = rowSums(across(starts_with("asfr")), na.rm = TRUE) / 1000, # 更新asfr系列列的值为 (原值/1000)/TFR across(starts_with("asfr"), ~ (.x / 1000) / TFR) )
starts_with("asfr")自动匹配所有以asfr开头的列,无需手动写列索引,列顺序变化也不影响结果na.rm = TRUE确保计算行和时忽略NA值,适配你的数据情况- 整个过程在一个管道中完成,不会丢失任何原始列,
asfr系列列名保持不变
方法2:基于列索引的base R方法
如果习惯用base R操作,可以通过列索引选择目标列,直接赋值更新:
# 定义asfr系列列的索引(示例中为第7到第41列) asfr_cols <- 7:41 # 复制原始数据,避免修改原数据集 sample_processed <- sample # 第一步:计算TFR列 sample_processed$TFR <- rowSums(sample_processed[, asfr_cols], na.rm = TRUE) / 1000 # 第二步:更新asfr系列列的值 sample_processed[, asfr_cols] <- (sample_processed[, asfr_cols] / 1000) / sample_processed$TFR
- 直接对目标列赋值更新,所有原始列都会保留
- 若数据存在NA,
rowSums需加na.rm = TRUE避免结果为NA
内容的提问来源于stack exchange,提问作者Azam Mirzaei
相关产品推荐
相关产品推荐

