R - 如何生成数据框中所有列组合的差异
Posted
技术标签:
【中文标题】R - 如何生成数据框中所有列组合的差异【英文标题】:R - How can I generate difference of all combinations of columns in a data frame 【发布时间】:2017-06-08 18:09:33 【问题描述】:例子:
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
我想要的是:
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)
或其他语法中的类似内容
我不想手动写出所有列的方程。假设我有 100 列开始,那将是 4950 列。我不可能写出来
您可以使用combn
的结果进行子集化,但添加那么多列通常是个坏主意;最好改成长形。
【参考方案1】:
我们可以在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】:给你
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。
【讨论】:
你真的不需要apply
;你可以做df[z[1,]] - df[z[2,]]
。【参考方案3】:
这对我有用:
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 与 cols 一起添加。 :)【参考方案4】:使用combn
生成2
(在调用中指定)colnames 的所有组合
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 完成它!【参考方案5】: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
【讨论】:
以上是关于R - 如何生成数据框中所有列组合的差异的主要内容,如果未能解决你的问题,请参考以下文章