non-numeric argument binary operator error - r

Not sure why I am getting a non-numeric argument binary operator error. Do I have some type mismatch going on?
for (j in 1:length(theta)) {
val = exp(y * sum(theta * random_data_vector) * y * random_data_vector[i])
val = val / (1 + exp(y * sum(theta * random_data_vector)))
theta[j] = theta[j] - (alpha * val)
}
Error:
Error in theta * random_data_vector :
non-numeric argument to binary operator
Values:
> head(theta)
[1] 0.02435863 -0.74310189 -0.63525839 0.56554085 -0.20599967 0.43164130
> head(random_data_vector)
[1] 0 0 0 0 0 0
> y
V9437
785 1
After FIRST iteration of for loop, theta looks like this:
> head(theta)
[[1]]
[1] NA
[[2]]
[1] -0.2368957
[[3]]
[1] 0.697332
[[4]]
[1] 0.6104201
[[5]]
[1] 0.8182983
[[6]]
[1] 0.7093492
For more information, the above is a snippet from my entire function I am trying to create around stochastic gradient descent.
data is a set of rows grabbed from a CSV
labels is 1 row grabbed from a CSV
alpha is a float
mnist = read.csv('mnist_train.csv', header=FALSE)
data = mnist[,mnist[nrow(mnist),]==0 | mnist[nrow(mnist),]==1, drop=FALSE]
labels = data[785,]
data = data[1:784,]
train = function(data, labels, alpha) {
theta = runif(nrow(data),-1,1)
decay_rate = .01
random_column_indexes = sample(ncol(data))
idx = 1
limit = length(random_column_indexes)
threshold = 1e-5
delta = 1000000
for (n in 1:ncol(data)) {
if (delta <= threshold) {
break
}
i = random_column_indexes[n]
random_data_vector = data[, i]
y = labels[i]
previous_theta = theta
for (j in 1:length(theta)) {
val = exp(y * sum(theta * random_data_vector) * y * random_data_vector[i])
val = val / (1 + exp(y * sum(theta * random_data_vector)))
theta[j] = theta[j] - (alpha * val)
}
alpha = alpha - decay_rate
delta = abs(previous_theta - theta)
}
return(theta)
}

I consider that the problem has to do with the subsetting of your objects. From the link you provided in the comments I see that your data is a data.frame object and you subset it using [. If you check the type of any data.frame e.g. typeof(iris) you can see that it is a "list".
When you use y = labels[i], your object will be a list, that's because:
when [ is applied to a list it always returns a list: it never gives you the contents of the list. To get the contents, you need [[ Advanced R by Hadley Wickham
Declare y as y <- labels[[i]] or subset labels from your data.frame as a vector doing as.numeric(data[785,])

Related

Error when calling a user-defined function within a while loop, but not when called directly

When I call the user defined function sRGB_to_CAM16UCS in the console, it displays the result as intended. But when I try to call it within a while loop it throws an error. Can somebody help me understand the error?
library(purrr)
library(tibble)
library(tidyr)
sRGB_to_CAM16UCS <- function(R255, G255, B255){
# Convert sRGB to 1931 CIE XYZ [IEC 61966-2–1:2003(E)]
## Convert to the range of 0 to 1
R1 <- R255 / 255
G1 <- G255 / 255
B1 <- B255 / 255
## Gamma Expansion of sRGB values
gamma_inverse <- function(RGB1){
if (RGB1 < -0.04045 | RGB1 > 0.04045){
((RGB1 + 0.055)/1.055)^2.4
} else {
RGB1/12.92
}
}
R_li <- gamma_inverse(R1)
G_li <- gamma_inverse(G1)
B_li <- gamma_inverse(B1)
# Convert linear RGB values to CIE XYZ
X <- 41.24 * R_li + 35.76 * G_li + 18.05 * B_li
Y <- 21.26 * R_li + 71.52 * G_li + 07.22 * B_li
Z <- 01.93 * R_li + 11.92 * G_li + 95.05 * B_li
# Convert XYZ to CAM16
## User defined Parameters
X_w <- 96.4212
Y_w <- 100
Z_w <- 82.5188
L_A <- 40
Y_b <- 20
surround <- 2
discounting <- FALSE
## Predefined functions and constants
### M16
M16 <- matrix(c(0.401288,-0.250268,-0.002079,
0.650173, 1.204414, 0.048952,
-0.051461, 0.045854, 0.953127), nrow = 3, ncol=3)
### lerp
lerp <- function(a,b,c){
(1 - c) * a + c * b
}
### Crop
crop <- function(a,b,c){
pmin(pmax(c, a), b)
}
### Define adapt
adapt <- function(component){
con <- (F_L * abs(component) * 0.01)^0.42
sign(component) * 400 * con / (con + 27.13)
}
### Define unadapt
unadapt <- function(component){
sign(component) * 100 / F_L * ((27.13* abs(component))/(400-abs(component)))^2.38095238095
}
# Calculations
## Calculate "c"
if (surround >=1){
c <- lerp(0.59, 0.69, surround-1)
}else{
c <- lerp(0.525, 0.59, surround)
}
## Calculate "F" and "N_c"
if (c >= 0.59){
N_c <- lerp(0.9, 1.0, (c - 0.59)/.1)
} else {
N_c <- lerp(0.8, 0.9, (c - 0.525)/0.065)
}
## Calculate "k"
k <- 1/(5*L_A + 1)
## Calculate F_L
F_L <- k^4 * L_A + 0.1 * (1-k^4)^2 * (5 * L_A)^0.33333333333
## Calculate n
n <- Y_b / Y_w
## Calculate z
z <- 1.48 + sqrt(n)
## Calculate N_bb
N_bb <- 0.725 * n^-0.2
## Calculate D
if (discounting == FALSE){
D <- crop(0,1,N_c* (1 - 1/3.6 * exp((-L_A - 42)/92)))
}else {
D <- 1
}
## Calculate the "RGB_w"
RGB_w <- matrix(c(M16[1,1] * X_w + M16[1,2] * Y_w + M16[1,3] * Z_w,
M16[2,1] * X_w + M16[2,2] * Y_w + M16[2,3] * Z_w,
M16[3,1] * X_w + M16[3,2] * Y_w + M16[3,3] * Z_w), nrow = 3, ncol=1)
# Calculate the "D_RGB"
D_RGB <- apply(RGB_w, c(1, 2), function(x)((1 - D) * 1 + D * Y_w/x))
# Calculate the "D_RGB_inv"
D_RGB_inv <- apply(D_RGB,c(1, 2),function(x)1/x)
# Calculate the "RGB_cw"
RGB_cw <- RGB_w*D_RGB
# Calculate RGB_aw
RGB_aw <- apply(RGB_cw, c(1,2), adapt)
# Calculate A_w
A_w <- N_bb * ( 2 * RGB_aw[1,1] + RGB_aw[2,1] + 0.05 * RGB_aw[3,1])
# Calculate RGB_a
R_a <- adapt((M16[1,1] * X + M16[1,2] * Y + M16[1,3] * Z) * D_RGB[1,1])
B_a <- adapt((M16[2,1] * X + M16[2,2] * Y + M16[2,3] * Z) * D_RGB[2,1])
G_a <- adapt((M16[3,1] * X + M16[3,2] * Y + M16[3,3] * Z) * D_RGB[3,1])
# Calculate Hue
a <- R_a + (-12 * G_a + B_a) / 11
b <- (R_a + G_a - 2 * B_a) / 9
h_rad <- atan2(b, a)
h_ucs <- h_rad*(180.0/pi)
# Calculate Lightness (J)
e_t <- 0.25 * (cos(h_rad + 2) + 3.8)
A <- N_bb * (2*R_a + G_a + 0.05*B_a)
J <- 100 * ((A / A_w)^(c*z))
J_ucs <- 1.7 * J / (1 + 0.007 * J)
# Calculate brightness (Q)
Q <- 4/c * sqrt(J/100) * (A_w + 4) * (F_L^0.25)
# Calculate chroma (C)
t <- (5000 / 13 * N_c * N_bb * e_t * sqrt(a*a + b*b)) / (R_a + G_a + 1.05 * B_a + 0.305)
alpha <- t^0.9*(1.64 - 0.29^n)^0.73
C <- alpha * sqrt(J/100)
# Calculate colorfulness (M)
M <- C * F_L^0.25
M_ucs <- log(1 + 0.0228 * M) / 0.0228
# Calculate redness-greenness(a)
a_ucs <- M * cos(h_rad)
# Calculate yellowness-blueness(b)
b_ucs <- M * sin(h_rad)
# Calculate Saturation (s)
s <- 50 * sqrt(alpha*c /(A_w + 4))
return(tibble(R255, G255, B255, h_ucs, J_ucs ,M_ucs ,a_ucs, b_ucs))
}
nc <- 5
rgb_vals <- tibble(r1 = rdunif(nc, b=255, a=0), g1 = rdunif(nc, b=255, a=0), b1 = rdunif(nc, b=255, a=0))
test <- 1
test_df <- tibble(h_ucs = numeric(), J_ucs = numeric(), M_ucs = numeric(), a_ucs = numeric(), b_ucs = numeric())
while(test <= nrow(rgb_vals)){
test_r <- sRGB_to_CAM16UCS(rgb_vals[test, 1],rgb_vals[test, 2],rgb_vals[test, 3])
test_df <- rbind(test_df, test_r)
test <- test + 1
}
output <- cbind(rgb_vals, test_df)
print(output)
openxlsx::write.xlsx(output, "rgb2camucs.xlsx")
threw an error as following
Error in atan2(b, a) : non-numeric argument to mathematical function
>
> output <- cbind(rgb_vals, test_df)
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 5, 0
> print(output)
Error in print(output) : object 'output' not found
UPDATE: If I wrap the a and b with as.numeric() function, it throws the following error message:
Error:
! Column names `r1`, `r1`, `r1`, `r1`, `r1`, and 1 more must not be duplicated.
Use .name_repair to specify repair.
Caused by error in `repaired_names()`:
! Names must be unique.
x These names are duplicated:
* "r1" at locations 1, 2, 3, 5, 6, etc.
Run `rlang::last_error()` to see where the error occurred.
>
This is because b and a are indeed non-numeric arguments. They are data.frames.
Replacing that line with h_rad <- atan2(b$r1, a$r1) makes it work as class(b$r1) results in numeric. Note that the last line of code where output is exported to an XLSX does not work.
You can also "unpack" your 1x1 data.frame using double brackets before calling your method, i.e., say test_r <- sRGB_to_CAM16UCS(rgb_vals[[test, 1]],rgb_vals[[test, 2]],rgb_vals[[test, 3]]) instead of test_r <- sRGB_to_CAM16UCS(rgb_vals[test, 1],rgb_vals[test, 2],rgb_vals[test, 3]) near the end of your code. This way you are passing the plain numbers to your function. This way, also the export to XLSX works.
I found this using RStudio's debugger, setting a breakpoint to that line and then entering class(b) into the console on the bottom.

loop though a matrix in R

I try to loop trough a matrix but cant find a easy and elegant way instead of writing many (>10) equations... Can anyone help me please?
My Matrix looks like this:
and I want to calculate the following:
(0 * 0 * 4/24) + (0 * 1 * 6/24) + (0 * 2 * 3/24) + (1 * 0 * 3/24) + (1 * 1 * 4/24) + (1 * 2 * 4/24)
instead of using
__
btw: my code for the matrix
vals<- c(4/24, 6/24, 3/24, 3/24, 4/24, 4/24)
x <- c(0,1)
y <- c(0,1,2)
df <- matrix(vals, byrow = TRUE, nrow = 2, ncol = 3,
dimnames = list(x,y))
instead of calculation each step manually, I think there should be a for-loop method, but cant figure it out..
A possible solution:
c(x %*% df %*% y)
#> [1] 0.5
Another possible solution, based on outer:
sum(outer(x, y, Vectorize(\(x,y) x*y*df[x+1,y+1])))
#> [1] 0.5
x <- c(0, 1)
y <- c(0, 1, 2)
vals<- c(4/24, 6/24, 3/24, 3/24, 4/24, 4/24)
mat <- matrix(vals, byrow = TRUE, nrow = 2, ncol = 3,
dimnames = list(x,y)) ## not a data frame; don't call it "df"
There is even a better way than a for loop:
sum(tcrossprod(x, y) * mat)
#[1] 0.5
sum((x %o% y) * df)
Explanation:
x %o% y gets the outer product of vectors x and y which is:
#> [,1] [,2] [,3]
#> [1,] 0 0 0
#> [2,] 0 1 2
Since that has the same dimensions as df, you can multiply the corresponding elements and get the sum: sum((x %o% y) * df)
If you are new to R (as I am), here is the loop approach.
result = 0
for (i in 1:length(x)) {
for (j in 1:length(y)) {
result = result + x[i] * y[j] * df[i, j]
}
}
result

optim in R, finding numeric solution

I need to find exact and numerical solutions to a function but my code in R shows Error in optim(start_val[i, ], g) :
function cannot be evaluated at initial parameters
that is my code:
g <- function(x) (3*x[1]+2*x[2]+4*x[3]-4)^2 + (4*x[1]+2*x[2]+4*x[3]-2)^2 + (1*x[1]+1*x[2]+4*x[3]-4)^2
start_val <- expand.grid(c(-10,0,10),c(-10,0,10),c(-10,0,10))
optim_on_a_multiple_grid <- function(start_val, fun, ...) {
opt_result <- sapply(1:nrow(start_val),
function(i) {
res <- optim(start_val[i,], g)
c(res[[1]], res[[2]], res[[4]])
})
rownames(opt_result) <-
c(paste("x_", 1:ncol(start_val),
"_start_val", sep = ""),
paste("x_", 1:ncol(start_val),
"_sol", sep = ""),
paste(c(deparse(substitute(
fun
)), "_min"), collapse = ""),
"convergence")
opt_result
}
round(optim_on_a_multiple_grid(expand.grid(c(-10, 0, 10), c(-10, 0, 10)), g), 3)
Please, point me at my mistakes and explain how to fix them, I am stuck on it for quite a while now
I do not know why you have alot of objects while your aim is to optimize:
Do
# Define g
g <- function(x){
a <- (3 * x[1] + 2 * x[2] + 4 * x[3] - 4)^2
b <- (4 * x[1] + 2 * x[2] + 4*x[3] - 2)^2
d <- (x[1] + x[2] + 4*x[3] - 4)^2
a +b +d
}
optim(par=c(0,0,1), fn=g)
$par
[1] -1.9998762 3.9996836 0.5000453
$value
[1] 8.468819e-09
$counts
function gradient
160 NA
$convergence
[1] 0
$message
NULL
If you need your code:
The problem lies at the very end of it:
You should have:
round(optim_on_a_multiple_grid(start_val, g), 3)

Coerce a function into an expression?

Is there any function or method that coerces a function object into an expression in R?
Suppose I have u = function (x, y) 2 * x^0.8 * y^0.2. What I would like to achieve is convert u into a call or expression object. Example, 2 * x^0.8 * y^0.2 with mode(.) == 'call' or expression(2 * x^0.8 * y^0.2)
I know that you can do something like:
str2lang(deparse(u)[[2]])
2 * x^0.8 * y^0.2
deparse can still be made to work for cases when functions have several lines.
ff = function(x, y) {
x = x + 1
y = y + 1
return(x+y)
}
str2lang(paste(deparse(ff)[-1], collapse='\n'))
{
x = x + 1
y = y + 1
return(x + y)
}
Is there a better way already implemented in R?
Use body. No packages are used.
b <- body(ff)
# test
eval(b, list(x = 3, y = 10))
## [1] 15
# compare to ff
ff(x = 3, y = 10)
## [1] 15

Implementing an algorithm to compute pi in R

I am trying to implement a variation of the Brent-Salamin algorithm in R. It works well for the first 25 iterations, but then, it behaves unexpectedly, returning negative results.
The algorithm I want to implement is:
initial values:
x_0 = 1; y_0 = 1/sqrt(2); z_0 = 1/2
x_n = (x_n-1 + y_n-1)/2
y_n = sqrt(x_n-1 * y_n-1)
z_n = z_n-1 - 2^n * (x_n^2-y_n^2)
p_n = (2 * x_n^2) / z_n
where n is the current iteration.
A more beautifully formatted formula is here.
The code I figured out is:
mypi <- function(n){
x = 1
y = 1/sqrt(2)
z = 1/2
iteration = 0
while(iteration < n){
iteration = iteration + 1
newx = (x + y) / 2
y = sqrt(x * y)
x = newx
z = z-(2^iteration * (x^2 - y^2))
p = (2 * x^2) / z
}
return(p)
}
Output:
> mypi(10)
[1] 3.141593
> mypi(20)
[1] 3.141593
> mypi(50)
[1] -33.34323
So as I am new to R, is there a bug in my code or is it the algorithm?
Your code simply messes up because it does not agree with the algorithm as written in the wiki page. A correct version looks like this:
mypi <- function(n){
x = 1
y = 1/sqrt(2)
z = 1/4
p <- 1
iteration = 0
while(iteration < n){
iteration = iteration + 1
newx = (x + y) / 2
y = sqrt(x * y)
# x = newx
# z = z-(2^iteration * (x^2 - y^2))
z = z- p* (x-newx)^2
p = 2*p
x = newx
}
(newx + y)^2/(4*z)
}
Gives
> mypi(10)
[1] 3.141593
> mypi(20)
[1] 3.141593
> mypi(50)
[1] 3.141593

Resources