My Problem
I have the following (simplified) dataframe df
:
A B C
[1,] 2 -5 20
[2,] -10 -1 10
[3,] 10 -10 0
I want to isolate just the values of the smallest magnitude:
[ 2, -1, 0 ]
How would I do that?
What I've Tried
So far I've just got it to show me what the minimum absolute value is per row:
MagMin <- vector()
for(i in 1:nrow(df)){
sub <- df[i,]
MagMin[i] <- min(abs(df[i,]))
}
Which gives me [2, 1, 0]
, but obviously, I've lost the signage for what way the smallest value goes.
I found a nice answer to the question in python, but I can't think how to apply it here!
CodePudding user response:
apply(mat, 1, function(z) z[which.min(abs(z))])
# [1,] [2,] [3,]
# 2 -1 0
Walk-through:
When you want the min-magnitude,
min(abs(val))
will return the positive of that, which you know ...val <- c(-10L, -1L, 10L) min(abs(val)) # [1] 1
We can use
which.min(abs(val))
to determine which in the vector is the min-magnitude, which returns an index on the vector:which.min(abs(val)) # [1] 2
Using that, we can extract the specific value (pos or neg) based on the min-magnitude:
val[which.min(abs(val))] # [1] -1
to repeat the operation for each row, we use
apply(mat, 1, ...)
. The1
is forMARGIN=1
which means "by row", and the third argument (FUN=
) is a function that takes exactly one argument and does something with it; in this case, the first time it's called,z
is effectivelymat[1,]
, with the valuesc(2, -5, 20)
; the second time, it's effectivelymat[2,]
with valuesc(-10, -1, 10)
; etc.
Data
mat <- structure(list(A = c(2L, -10L, 10L), B = c(-5L, -1L, -10L), C = c(20L, 10L, 0L)), class = "data.frame", row.names = c("[1,]", "[2,]", "[3,]"))