Reputation: 77
Here's some example data for this problem, let's call this example dataset df:
df$x
obs x
1 2
2 4
3 8
4 16
What I'd like to accomplish is to find the difference for each x against all other xs for all x and store those differences in an object.
Here's what the math should look like:
some code later:
result_df
obs col1 col2 col3
1 2-4 2-8 2-16
2 4-2 4-8 4-16
3 8-2 8-4 8-16
4 16-2 16-4 16-8
What I've tried doing so far is something like this:
for (i in 1:nrow(df)){
#Create empty matrix
mat<-matrix(rep(0,(nrow(df))*(nrow(df)-1)),ncol=nrow(df)-1,nrow=nrow(df))
#occupy matrix with desired results
mat[i,]<-df$x[i]-df$x[i+1]
print(mat)
}
I intended this code to be valid for the first row of my result_df in my example (I guess I would have to create another loop to do it for each given x?), but it doesn't give me the desired results.
I hope that's clear. Thanks! It'd be great to me able to do this in base R so I get a better grasp of it.
Upvotes: 1
Views: 316
Reputation: 887038
Here is another option using CJ
from data.table
library(data.table)
matrix(CJ(df$x, df$x)[V1 != V2, V1-V2], nrow(df), byrow=TRUE)
# [,1] [,2] [,3]
#[1,] -2 -6 -14
#[2,] 2 -4 -12
#[3,] 6 4 -8
#[4,] 14 12 8
Or a base R
option is outer
m1 <- outer(df$x, df$x, `-`)
cbind(obs = 1:4, matrix(m1[m1!=0], nrow= nrow(df), byrow = TRUE,
dimnames = list(NULL, paste0('col', 1:3))))
# obs col1 col2 col3
#[1,] 1 2 6 14
#[2,] 2 -2 4 12
#[3,] 3 -6 -4 8
#[4,] 4 -14 -12 -8
This can be converted to data.frame
by wrapping with as.data.frame
Upvotes: 0
Reputation: 14360
Another option would be to use expand.grid
:
expanded <- expand.grid(df$x, df$x)
subtr <- expanded[!(expanded$Var1 == expanded$Var2), "Var2"] - expanded[!(expanded$Var1 == expanded$Var2), "Var1"]
data.frame(matrix(subtr, nrow = nrow(df), byrow = T))
# X1 X2 X3
#1 -2 -6 -14
#2 2 -4 -12
#3 6 4 -8
#4 14 12 8
Upvotes: 0
Reputation: 3875
You could do it using sapply
:
d=t(sapply(1:nrow(df),function(i) df$x[i]-df$x[-i]))
res_df=data.frame(df$obs,d)
names(res_df)=c("obs",paste0("col",c(1:3)))
This returns:
obs col1 col2 col3
1 1 -2 -6 -14
2 2 2 -4 -12
3 3 6 4 -8
4 4 14 12 8
Upvotes: 3