每两列减去一次

ska*_*kan 7 regex r

想象一下,我有一个这样的数据帧(或所有月份的名称)

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个组,我可能想要做一些事情,比如添加所有数字.通用的解决方案会很棒.

我首先尝试通过将其转换为长格式,稍​​后使用聚合操作并将其转换回宽格式来实现,但也许直接以宽格式进行操作要容易得多.我知道问题主要与使用有效的正则表达式有关.

R,data.table或dplyr,长格式拆分列号

我不介意速度,但最简单的解决方案.任何套餐都很好.

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组的差异)

最佳选择不是手动删除第一列,而是将所有列拆分为单列和多列.

Raa*_*aad 3

使用基本 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)

对于更一般的应用程序,可以用正则表达式代替这种粘贴方法。