Reputation: 107
I want to create a new column where I assign the value closest to the values of a list, based on another column. This is my data:
df <- data.frame(AV=c("A", "A", "A", "A", "A", "B", "B", "B", "B"),
var=c( 0.1, 0.2, 1.5, 1.8, 8, 1, 1.4, 13, 3))
x <- c(0.5, 1, 2, 5, 10, 20, 40, 80)
for (i in df$var){
res <- x[which.min(abs(x - i))]
print(res)}
[1] 0.5
[1] 0.5
[1] 1
[1] 1
[1] 10
[1] 1
[1] 1
[1] 10
[1] 2
I want res
to be a new column in my dataframe, however, and struggle with implementing it.
f = function(x){x[which.min(abs(x - i))]}
for (i in df$var){
df$res <- apply(df, 1, f)
}
f = function(x){x[which.min(abs(x - i))]}
for (i in df$var_floor){
for (j in df$var_floor){
df$res <- apply(df, 1, f)
}
#Leads to: Error in x - i : non-numeric argument to binary operator
f = function(x){x[which.min(abs(x - i))]}
for (i in df$var){
res <- apply(df, 1, f)
}
#Leads to: Error in x - i : non-numeric argument to binary operator
Apply without the for loop
didn't work either.
How can I assign the closest value for each row?
Upvotes: 1
Views: 60
Reputation: 887981
One option is findInterval
from base R
transform(df, res = x[findInterval(var, x)+1])
Upvotes: 1
Reputation: 10781
We can use sapply
:
df$res <- sapply(df$var, FUN = function(v) x[which.min(abs(x - v))])
# AV var res
# 1 A 0.1 0.5
# 2 A 0.2 0.5
# 3 A 1.5 1.0
# 4 A 1.8 2.0
# 5 A 8.0 10.0
# 6 B 1.0 1.0
# ...
Upvotes: 3