I have a list of 3 vectors, X
, Y
, and Z
. I want to subtract similarly named elements of these 3 vectors. That is, similarly named elements subtracted throughout like so: X - Y - Z
.
Also, if an element (here ChandlerA
and Trus.Hsu
in X
) appears only once in one vector but not in others, then I want to skip that element altogether.
My desired output is:
c(Bit.KnoA = -2, Bit.KnoB = -4, Bit.KnoC = -2, Ellis.etal = 3, Mubarak = 3, sheenA = 5, Shin.Ellis = 5, Sun = 7)
Is it possible to achieve this in Base R?
V = list(X = c(Bit.KnoA = 4, Bit.KnoB = 1, Bit.KnoC = 2, ChandlerA = 3, Ellis.etal =4,
Mubarak=5, SheenA=6, Shin.Ellis=7 , Sun = 8, Trus.Hsu=3 ),
Y = c(Bit.KnoA = 6, Bit.KnoB = 3, Bit.KnoC = 4, Ellis.etal =1, Mubarak=2,
SheenA=1, Shin.Ellis=2 , Sun = 1),
Z = c(Bit.KnoB = 2) )
V[[1]] - V[[2]] - V[[3]] # all elements regardless of names are subtracted
We can do this more compactly with aggregate
and Reduce
with(aggregate(values ~ ind, subset(do.call(rbind, lapply(V, stack)),
ind %in% names(which(table(ind) > 1))),
FUN = function(x) Reduce(`-`, x)), setNames(values, ind))
# Bit.KnoA Bit.KnoB Bit.KnoC Ellis.etal Mubarak SheenA Shin.Ellis Sun
# -2 -4 -2 3 3 5 5 7
or using tidyverse
library(tidyverse)
map_df(V, enframe) %>%
group_by(name) %>%
filter(n() > 1) %>%
summarise(value = reduce(value, `-`)) %>%
deframe
# Bit.KnoA Bit.KnoB Bit.KnoC Ellis.etal Mubarak SheenA Shin.Ellis Sun
# -2 -4 -2 3 3 5 5 7
Here is one base R option
#Copy contents of V
V1 <- V
#Remove names of V1
names(V1) <- NULL
#unlist the values
vals <- unlist(V1)
#Find out names which occur only once
delete_names <- names(Filter(function(x) x == 1, table(names(vals))))
#Remove them from the list
new_vals <- vals[!names(vals) %in% delete_names]
#Subtract values from each similar named element.
sapply(unique(names(new_vals)), function(x) Reduce(`-`, new_vals[names(new_vals) == x]))
# Bit.KnoA Bit.KnoB Bit.KnoC Ellis.etal Mubarak SheenA Shin.Ellis Sun
# -2 -4 -2 3 3 5 5 7