How can I take pairwise parallel maximum between two vectors?
Pairwise maximum, pmax(a, b)
, will give c(3,4,6)
.
a <- c(3,3,5,NA,1)
b <- c(2,4,6,0,NA)
pmax(a, b)
# [1] 3 4 6 NA NA
pmax(a, b, na.rm = TRUE)
# [1] 3 4 6 0 1
There is also a pairwise minimum
pmin(a, b)
# [1] 2 3 5 NA NA
pmin(a, b, na.rm = TRUE)
# [1] 2 3 5 0 1
And a pairwise sum, which I pulled from this question/answer has been very useful to me at times:
psum(a, b) # == a + b
# [1] 5 7 11 NA NA
psum(a, b, na.rm = TRUE)
# [1] 5 7 11 0 1
psum(c(-1, NA, 4), c(0, NA, NA))
# [1] -1 NA NA
psum(c(-1, NA, 4), c(0, NA, NA), na.rm = TRUE)
# [1] -1 NA 4
psum <- function(..., na.rm = FALSE) {
dat <- do.call(cbind, list(...))
res <- rowSums(dat, na.rm = na.rm)
idx_na <- !rowSums(!is.na(dat))
res[idx_na] <- NA
res
}
How to find the max of 2 vectors element-wise?
We can use pmax
in base R
pmax(a, b, na.rm = TRUE)
#[1] 0 2 9 3
Finding maximum from variables in r
You can use Map
. Map applies a function to the corresponding elements of given vectors.
probsA <- c(2.634872e-02, 6.709075e-03, 1.107573e-04, 1.708307e-03, 2.820171e-05)
probsB <- c(0.0013311712, 0.0012295459, 0.0009688963, 0.0011356790, 0.0008949280)
Map(max, probsA, probsB)
[[1]]
[1] 0.02634872
[[2]]
[1] 0.006709075
[[3]]
[1] 0.0009688963
[[4]]
[1] 0.001708307
[[5]]
[1] 0.000894928
R: Parallel second largest value from multiple vectors
Here's another option:
R> apply(tbl[,2:4], 1, function(x) x[rank(1/x) == 2])
#[1] 20000 15000 NA NA
which can then be assigned to your object normally, e.g. as in @akrun's answer.
tbl <- read.table(
text = " Name Fund-A Fund-B Fund-C SecondLargest(Desired)
John 30000 20000 10000 20000
Tom NA 40000 15000 15000
Sarah 5000 NA NA NA
Kate NA NA NA NA",
header=TRUE,
stringsAsFactors=FALSE)
Return maximum of conditionally selected pairs from a vector in R
We could create a function to split
the vector by 'n' elements, loop over the list
, create a matrix
with nrow
specified as 2, use pmax
to do elementwise
max after converting to data.frame
, return the output by unlist
ing the list
f1 <- function(vec, n) {
lst1 <- split(vec, as.integer(gl(length(vec), n, length(vec))))
unname(unlist(lapply(lst1, function(x)
do.call(pmax, as.data.frame(t(matrix(x, nrow = 2, byrow = TRUE)))))))
}
-output
> f1(A, 6)
[1] 4 3 4 3 4 5
If the length is not a multiple of 3 or 6, another option is to do a group by operation with tapply
after splitting
unname(unlist(lapply(split(A, as.integer(gl(length(A), 6,
length(A)))), function(x) tapply(x, (seq_along(x)-1) %% 3 + 1, FUN = max))))
[1] 4 3 4 3 4 5
data
A <- c(1, 2, 2, 4, 3, 4, 3, 4, 5, 3, 4, 5)
Combine vectors in R using vectorization where values only sum if they are not equal
Looks like you are trying to implement the OR
gate .You can use pmax
:
pmax(aa, bb)
#[1] 1 1 1 1 0
How to perform pairwise operation like `%in%` and set operations for a list of vectors
We could use outer(x, y, FUN)
. x
and y
need not be a "numeric" input like numerical vector / matrix; a vector input like "list" / "matrix list" is also allowed.
For example, to apply pairwise "%in%"
operation, we use
z <- outer(lst, lst, FUN = Vectorize("%in%", SIMPLIFY = FALSE, USE.NAMES = FALSE))
# vec1 vec2 vec3 vec4
#vec1 Logical,2 Logical,2 Logical,2 Logical,2
#vec2 Logical,3 Logical,3 Logical,3 Logical,3
#vec3 Logical,4 Logical,4 Logical,4 Logical,4
#vec4 Logical,5 Logical,5 Logical,5 Logical,5
Since "%in%"
itself is not vectorized, we use Vectorized("%in%")
. We also need SIMPLIFY = FALSE
, so that FUN
returns a length-1 list for each pair (x[[i]], y[[j]])
. This is important, as outer
works like:
y[[4]] | FUN(x[[1]], y[[4]]) FUN(x[[2]], y[[4]]) FUN(x[[1]], y[[4]]) FUN(x[[2]], y[[4]])
y[[3]] | FUN(x[[1]], y[[3]]) FUN(x[[2]], y[[3]]) FUN(x[[1]], y[[3]]) FUN(x[[2]], y[[4]])
y[[2]] | FUN(x[[1]], y[[2]]) FUN(x[[2]], y[[2]]) FUN(x[[1]], y[[2]]) FUN(x[[2]], y[[4]])
y[[1]] | FUN(x[[1]], y[[1]]) FUN(x[[2]], y[[1]]) FUN(x[[1]], y[[1]]) FUN(x[[2]], y[[4]])
------------------- ------------------- ------------------- -------------------
x[[1]] x[[2]] x[[3]] x[[4]]
It must be satisfied that length(FUN(x, y)) == length(x) * length(y)
. While if SIMPLIFY = FALSE
, this does not necessarily hold.
The result z
above is a "matrix list", with class(z)
being "matrix", but typeof(z)
being "list". Read Why is this matrix not numeric? for more.
If we want to further apply some summary function to each element of z
, we could use lapply
. Here I would offer two examples.
Example 1: Apply any()
Since any(a %in% b)
is as same as any(b %in% a)
, i.e., the operation is symmetric, we only need to work with the lower triangular of z
:
lz <- z[lower.tri(z)]
lapply
returns an unnamed list, but for readability we want a named list. We may use matrix index (i, j)
as name:
ind <- which(lower.tri(z), arr.ind = TRUE)
NAME <- paste(ind[,1], ind[,2], sep = ":")
any_lz <- setNames(lapply(lz, any), NAME)
#List of 6
# $ 2:1: logi FALSE
# $ 3:1: logi TRUE
# $ 4:1: logi TRUE
# $ 3:2: logi TRUE
# $ 4:2: logi FALSE
# $ 4:3: logi TRUE
Set operations like intersect
, union
and setequal
are also symmetric operations which we can work with similarly.
Example 2: Apply which()
which(a %in% b)
is not a symmetric operation, so we have to work with the full matrix.
NAME <- paste(1:nrow(z), rep(1:nrow(z), each = ncol(z)), sep = ":")
which_z <- setNames(lapply(z, which), NAME)
# List of 16
# $ 1:1: int [1:2] 1 2
# $ 2:1: int(0)
# $ 3:1: int [1:2] 1 2
# $ 4:1: int 3
# $ 1:2: int(0)
# $ 2:2: int [1:3] 1 2 3
# ...
Set operations like setdiff
is also asymmetric and can be dealt with similarly.
Alternatives
Apart from using outer()
, we could also use R expressions to obtain the z
above. Again, I take binary operation "%in%"
as an example:
op <- "'%in%'" ## operator
lst_name <- names(lst)
op_call <- paste0(op, "(", lst_name, ", ", rep(lst_name, each = length(lst)), ")")
# [1] "'%in%'(vec1, vec1)" "'%in%'(vec2, vec1)" "'%in%'(vec3, vec1)"
# [4] "'%in%'(vec4, vec1)" "'%in%'(vec1, vec2)" "'%in%'(vec2, vec2)"
# ...
Then we can parse and evaluate these expressions within lst
. We may use combination index for names of the resulting list:
NAME <- paste(1:length(lst), rep(1:length(lst), each = length(lst)), sep = ":")
z <- setNames(lapply(parse(text = op_call), eval, lst), NAME)
# List of 16
# $ 1:1: logi [1:2] TRUE TRUE
# $ 2:1: logi [1:3] FALSE FALSE FALSE
# $ 3:1: logi [1:4] TRUE TRUE FALSE FALSE
# $ 4:1: logi [1:5] FALSE FALSE TRUE FALSE FALSE
# $ 1:2: logi [1:2] FALSE FALSE
# ...
Related Topics
Overlay Data Onto Background Image
Update Subset of Data.Table Based on Join
Efficient Way to Filter One Data Frame by Ranges in Another
Chi Square Analysis Using for Loop in R
Why Do Some Unicode Characters Display in Matrices, But Not Data Frames in R
Lib Unspecified & Error in Loadnamespace
R Loop for Variable Names to Run Linear Regression Model
Add Nas to Make All List Elements Equal Length
Print "Pretty" Tables for H2O Models in R
Assign Intermediate Output to Temp Variable as Part of Dplyr Pipeline
How to Replace Nas When Joining Two Data Frames with Dplyr
Position of the Sun Given Time of Day, Latitude and Longitude