R - 如何在数据框中生成所有列的组合差异?

4

例子:

df <- data.frame(A=1:5, B=seq(0,10,2), C=seq(0,15,3))  
df  
A  B  C  
1  2  3  
2  4  6  
3  6  9  
4  8 12  
5 10 15  

What I want is:

A B C (A-B) (A-C) (B-C)  
1 2 3 -1 -2 -1  
2 4 6 -2 -4 -2  
3 6 9 -3 -6 -3  
4 8 12 -4 -8 -4  
5 10 15 -5 -10 -5  

这是一个示例。在我的问题中,我有超过100列。
有什么建议在R中如何处理这个问题吗?


使用dplyr,df %>% mutate(ab = A - B, ac = A - C, bc = B - C),或者在其他语法中类似的操作。 - alistaire
我不想手动为所有列编写方程式。假设我一开始有100列,那将是4950列。我不可能手写这个。 - user124543131234523
你可以使用combn的结果来进行子集操作,但通常不建议添加那么多列;最好将其转换为长格式。 - alistaire
非常感谢提供一个 dplyr 的解决方案。 - CyG
5个回答

4
我们可以在combn函数中使用FUN参数。
combn(seq_along(df), 2, FUN = function(x) df[,x[1]]- df[,x[2]])
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,]   -1   -2    0   -2   -1    1   -1    2    0    -2
#[2,]   -2   -4   -4   -7   -2   -2   -5    0   -3    -3
#[3,]   -3   -6   -8  -12   -3   -5   -9   -2   -6    -4
#[4,]   -4   -8  -12  -17   -4   -8  -13   -4   -9    -5
#[5,]   -5  -10  -16  -22   -5  -11  -17   -6  -12    -6

此外,combn 接受 data.frame 作为参数,因此只需:
combn(df, 2, FUN = function(x) x[,1]-x[,2])
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,]   -1   -2    0   -2   -1    1   -1    2    0    -2
#[2,]   -2   -4   -4   -7   -2   -2   -5    0   -3    -3
#[3,]   -3   -6   -8  -12   -3   -5   -9   -2   -6    -4
#[4,]   -4   -8  -12  -17   -4   -8  -13   -4   -9    -5
#[5,]   -5  -10  -16  -22   -5  -11  -17   -6  -12    -6

数据

df <- data.frame(A=1:5, B=seq(2,10,2), C=seq(3,15,3), d=seq(1,25,5), e=seq(3,31,6))

2

使用combn函数,该函数生成指定列名中所有2个元素的组合(在函数调用中指定)。

m = data.frame(combn(colnames(df),2), stringsAsFactors = F)
m
#  X1 X2 X3
#1  A  A  B
#2  B  C  C

df1 = data.frame(lapply(m, function(x) df[[x[2]]] - df[[x[1]]]))
colnames(df1) = lapply(m, function(x) paste(x[2], x[1], sep="-"))
cbind(df,df1)
#  A B  C B-A C-A C-B
#1 1 0  0  -1  -1   0
#2 2 2  3   0   1   1
#3 3 4  6   1   3   2
#4 4 6  9   2   5   3
#5 5 8 12   3   7   4

@user3305645编辑回答,使用colnames来完善它! - joel.wilson

2

这里是您需要的内容

df <- data.frame(A=1:5, B=seq(2,10,2), C=seq(3,15,3), d=seq(1,25,5), e=seq(3,31,6))

> df
  A  B  C  d  e
1 1  2  3  1  3
2 2  4  6  6  9
3 3  6  9 11 15
4 4  8 12 16 21
5 5 10 15 21 27

z = combn(1:ncol(df),2)

> z
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    1    1    1    2    2    2    3    3     4
[2,]    2    3    4    5    3    4    5    4    5     5

y = apply(z,2,function(x){
  df[,x[1]]-df[,x[2]]
})

结果:

> y
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   -1   -2    0   -2   -1    1   -1    2    0    -2
[2,]   -2   -4   -4   -7   -2   -2   -5    0   -3    -3
[3,]   -3   -6   -8  -12   -3   -5   -9   -2   -6    -4
[4,]   -4   -8  -12  -17   -4   -8  -13   -4   -9    -5
[5,]   -5  -10  -16  -22   -5  -11  -17   -6  -12    -6

矩阵 z 告诉你哪一对列被减去了。

你意识到如果数据框 df 有100列,所有的组合加起来总共有4950个。


1
你其实不需要使用 apply 函数;你可以直接使用 df[z[1,]] - df[z[2,]] - alistaire

2
这对我有用:
col_diff<-function(df)
{
    dif_fn<-function(obj){return(obj[[1]]-obj[[2]])}
    tmp_fn<-function(inp_row){unlist(combn(inp_row,2,FUN=dif_fn,simplify = FALSE))}
    intres<-t(apply(df,1,tmp_fn))
    colnames(intres)<-unlist(combn(colnames(df),2,simplify = FALSE,FUN=function(obj){paste(obj[[1]],obj[[2]],sep="-")}))
    temp<-cbind(df, intres)
    return(temp)

}

应用于您的输入:

 df <- data.frame(A=1:5, B=seq(2,10,2), C=seq(3,15,3))  
df
  A  B  C
1 1  2  3
2 2  4  6
3 3  6  9
4 4  8 12
5 5 10 15

col_diff(df)
   A  B  C A-B A-C B-C
1 1  2  3  -1  -2  -1
2 2  4  6  -2  -4  -2
3 3  6  9  -3  -6  -3
4 4  8 12  -4  -8  -4
5 5 10 15  -5 -10  -5

@user3305645 是的,我想我应该在列名中添加colnames。 :) - curious_cat

1
通过mapply
# the data: create the input data frame with mapply for fun
df <- as.data.frame(mapply(function(i,j) seq(0, 5*i, j), 1:5, 1:5))  
names(df) <- LETTERS[1:5]
df 
#  A  B  C  D  E
#1 0  0  0  0  0
#2 1  2  3  4  5
#3 2  4  6  8 10
#4 3  6  9 12 15
#5 4  8 12 16 20
#6 5 10 15 20 25

# now use mapply to solve our problem
pairs <- combn(seq_len(ncol(df)), 2) # find all possible pairs
mapply(function(i,j)df[,i]-df[,j], pairs[1,], pairs[2,])
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,]    0    0    0    0    0    0    0    0    0     0
#[2,]   -1   -2   -3   -4   -1   -2   -3   -1   -2    -1
#[3,]   -2   -4   -6   -8   -2   -4   -6   -2   -4    -2
#[4,]   -3   -6   -9  -12   -3   -6   -9   -3   -6    -3
#[5,]   -4   -8  -12  -16   -4   -8  -12   -4   -8    -4
#[6,]   -5  -10  -15  -20   -5  -10  -15   -5  -10    -5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接