想象一下,我有一个这样的数据帧(或所有月份的名称)
set.seed(1)
mydata <- data.frame()
mydata <- rbind(mydata,c(1,round(runif(20),3)))
mydata <- rbind(mydata,c(2,round(runif(20),3)))
mydata <- rbind(mydata,c(3,round(runif(20),3)))
colnames(mydata) <- c("id", paste0(rep(c('Mary', 'Bob', 'Dylan', 'Tom', 'Jane', 'Sam', 'Tony', 'Luke', 'John', "Pam"), each=2), 1:2))
Run Code Online (Sandbox Code Playgroud)
.
id Mary1 Mary2 Bob1 Bob2 Dylan1 Dylan2 Tom1 Tom2 Jane1 Jane2 Sam1 Sam2 Tony1 Tony2 Luke1 Luke2 John1 John2 Pam1 Pam2
1 0.266 0.372 0.573 0.908 0.202 0.898 0.945 0.661 0.629 0.062 0.206 0.177 0.687 0.384 0.770 0.498 0.718 0.992 0.380 0.777
2 0.935 0.212 0.652 0.126 0.267 0.386 0.013 0.382 0.870 0.340 0.482 0.600 0.494 0.186 0.827 0.668 0.794 0.108 0.724 0.411
3 0.821 0.647 0.783 0.553 0.530 0.789 0.023 0.477 0.732 0.693 0.478 0.861 0.438 0.245 0.071 0.099 0.316 0.519 0.662 0.407
Run Code Online (Sandbox Code Playgroud)
通常有更多列.
我想添加列(由您决定将它们添加到右侧,或者使用这些新列创建一个新的数据帧)每两个减去...(*)
id, Mary1-Mary2, Bob1-Bob2, Dylan1-Dylan2, Tom1-Tom2, Jane1-Jane2,...
Run Code Online (Sandbox Code Playgroud)
这种操作很常见.
我想通过名字而不是按职位来做,以防止问题,如果他们不连续.甚至可能会发生一些列没有它的"双胞胎"列,只是保持原样,或者现在忽略这种复杂情况.
(*)列的名称有前缀和数字.而不是仅仅减去两列我可以有5个组,我可能想要做一些事情,比如添加所有数字.通用的解决方案会很棒.
我首先尝试通过将其转换为长格式,稍后使用聚合操作并将其转换回宽格式来实现,但也许直接以宽格式进行操作要容易得多.我知道问题主要与使用有效的正则表达式有关.
我不介意速度,但最简单的解决方案.任何套餐都很好.
PD:如果我添加一个孤独的列,所有代码都会失败.set.seed(1)
mydata <- data.frame()
mydata <- rbind(mydata,c(1,round(runif(21),3)))
mydata <- rbind(mydata,c(2,round(runif(21),3)))
mydata <- rbind(mydata,c(3,round(runif(21),3)))
colnames(mydata) <- c(c("id", paste0(rep(c('Mary', 'Bob', 'Dylan', 'Tom', 'Jane', 'Sam', 'Tony', 'Luke', 'John', "Pam"), each=2), 1:2)),"Lola" )
Run Code Online (Sandbox Code Playgroud)
我知道我可以手动过滤它,但如果结果是每对的差异(*)并且单独留下孤独的列会更好.(如果是第2组的差异)
最佳选择不是手动删除第一列,而是将所有列拆分为单列和多列.
使用基本 R 怎么样:
cn <- unique(gsub("\\d", "", colnames(mydata)))[-1]
sapply(cn, function(x) mydata[[paste0(x, 1)]] - mydata[[paste0(x, 2)]] )
Run Code Online (Sandbox Code Playgroud)
您可以将此方法用于任意数量的组。例如,这将返回带有后缀 1 或 2 的名称的行总和:
sapply(cn, function(x) rowSums(mydata[, paste0(x, 1:2)]))
Run Code Online (Sandbox Code Playgroud)
对于更一般的应用程序,可以用正则表达式代替这种粘贴方法。