DJ-AFC
DJ-AFC

Reputation: 569

Subtract lists from each other

I am trying to subtract all files contained in one list from all files in another list. I have 64 items in both lists, with the data structured as follows:

FUTURE    List of 64

file1 :'data.frame': 240 obs of 4 variables:
..$V1: int [1:240] 1986 1986 1986 1986...
..$V2: int [1:240] 1 2 3 4...
..$V3: int [1:240] 16 15 16 16...
..$V4: int [1:240] 154 118 137 128...
----------------------------------------------
file64:'data.frame': 240 obs of 4 variables:
..$V1: int [1:240] 1986 1986 1986 1986...
..$V2: int [1:240] 1 2 3 4...
..$V3: int [1:240] 16 15 16 16...
..$V4: int [1:240] 122 189 107 114...
----------------------------------------------

    BASE    List of 64

file1 :'data.frame': 240 obs of 4 variables:
..$V1: int [1:240] 1986 1986 1986 1986...
..$V2: int [1:240] 1 2 3 4...
..$V3: int [1:240] 16 15 16 16...
..$V4: int [1:240] 133 178 157 146...
----------------------------------------------
file64:'data.frame': 240 obs of 4 variables:
..$V1: int [1:240] 1986 1986 1986 1986...
..$V2: int [1:240] 1 2 3 4...
..$V3: int [1:240] 16 15 16 16...
..$V4: int [1:240] 125 177 157 133...
----------------------------------------------

I simply want to subtract the fourth column ($V4) of all files contained in the BASE list from the same column of all files contained in the FUTURE list.

If these were simple dataframes I could just use:

CALC=FUTURE$V4-BASE$V4

but of course it is a bit more complicated with lists.

I have tried:

CALC=lapply(FUTURE, function(x) x["V4"] - BASE["V4"])

but I get the error message:

 Error in data.frame(value, row.names = rn, check.names = FALSE, check.rows  = FALSE) :
row names supplied are of the wrong length 

Any ideas as to how to remedy this?

Upvotes: 2

Views: 1851

Answers (2)

Akhil Nair
Akhil Nair

Reputation: 3274

To further my comment above, a one liner to map the lists on to each other

do.call(cbind, purrr::map2(BASE, FUTURE, ~ .x[, 4] - .y[, 4]))

Upvotes: 3

akrun
akrun

Reputation: 887038

We can use Map to subtract columns from the corresponding list elements of 'BASE' and 'FUTURE'.

CALC <- setNames(data.frame(Map(function(x, y) x[,4]-y[,4], 
                           BASE, FUTURE)), paste0('V', seq_along(BASE)))

As the OP had used lapply, one way with lapply would be to loop through the sequence of one of the list, use that index to subset both lists and substract the 4th column.

lst <- lapply(seq_along(BASE), function(i) BASE[[i]][,4]-FUTURE[[i]][,4])
do.call(cbind, lst) 

data

set.seed(24)
BASE <- lapply(1:4, function(i) 
            as.data.frame(matrix(sample(0:9, 5*10, replace=TRUE), ncol=5)))
set.seed(48)
FUTURE <- lapply(1:4, function(i) 
    as.data.frame(matrix(sample(0:9, 5*10, replace=TRUE), ncol=5)))

Upvotes: 2

Related Questions