I have an assignment for class that tasks me with creating a function in R that takes in a vector of values and converts them between Fahrenheit, Celsius and Kelvin. The example that I try to run through my code should produce a return vector that contains only 3 values, yet it is returning a vector that holds 26 values.
Here is my code below:
convTemp <- function(x, from = "C", to = "F") {
newX <- vector("double", length(x))
if (from == to) {
warning("Your 'from' parameter is the same as your 'to' parameter!") # From and To are same temperature scale
}
if (from == "C" && to == "F") { # Celsius to Fahrenheit
for (i in x) {
newX[i] <- ((9/5)*x[i] 32)
}
}
if (from == "C" && to == "K") { # Celsius to Kelvin
for (i in x) {
newX[i] <- (x[i] 273.15)
}
}
if (from == "F" && to == "C") { # Fahrenheit to Celsius
for (i in x) {
newX[i] <- ((x[i]-32)*(5/9))
}
}
if (from == "K" && to == "C") { # Kelvin to Celsius
for (i in x) {
newX[i] <- (x[i]-273.15)
}
}
if (from == "F" && to == "K") { # Fahrenheit to Kelvin
for (i in x) {
newX[i] <- ((((x[i]-32)*5)/9) 273.15)
}
}
if (from == "K" && to == "F") { # Kelvin to Fahrenheit
for (i in x) {
newX[i] <- ((((x[i]-273.15)*9)/5) 32)
}
}
return(newX)
}
convTemp(c(35,40,45), from="F", to="K")
And here is the output I'm receiving:
[1] 0 0 0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[26] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
So I'm not sure why the function is returning such a large vector of missing values when it should be returning a vector of 3 Kelvin values.
CodePudding user response:
Since R is vectorized, you do not need the for-loops. Check the code below to see how to better write your function:
convTemp <- function(x, from = "C", to = "F") {
stopifnot(c(from, to) %in% c('C', 'F', 'K'))# IN CASE YOU INPUT A DIFFERENT ARGUMENT OTHER THAN C,F, AND K
if (from == to) {
warning("Your 'from' parameter is the same as your 'to' parameter!") # From and To are same temperature scale
}
if (from == "C"){
if (to == "F") 9/5 * x 32 # Celsius to Fahrenheit
else (x 273.15) # Celsius to Kelvin
}
else if (from == "F") {
if(to == "C") (x -32) * 5/9 # Fahrenheit to Celsius
else (x - 32) * 5/9 273.15 # Fahrenheit to Kelvin
}
else {
if(to == 'C')(x - 273.15) # Kelvin to Celsius
else (x-273.15) * 9/5 32 # Kelvin to Fahrenheit
}
}
convTemp(c(35,40,45), from="F", to="K")
[1] 274.8167 277.5944 280.3722
CodePudding user response:
In the code (assuming it is a coding exercise), we need not loop over the values (for(i in x)
) but loop over the sequence (for(i in seq_along(x))
)
convTemp <- function(x, from = "C", to = "F") {
newX <- vector("double", length(x))
if (from == to) {
warning("Your 'from' parameter is the same as your 'to' parameter!") # From and To are same temperature scale
}
if (from == "C" && to == "F") { # Celsius to Fahrenheit
for (i in seq_along(x)) {
newX[i] <- ((9/5)*x[i] 32)
}
}
if (from == "C" && to == "K") { # Celsius to Kelvin
for (i in seq_along(x)) {
newX[i] <- (x[i] 273.15)
}
}
if (from == "F" && to == "C") { # Fahrenheit to Celsius
for (i in seq_along(x)) {
newX[i] <- ((x[i]-32)*(5/9))
}
}
if (from == "K" && to == "C") { # Kelvin to Celsius
for (i in seq_along(x)) {
newX[i] <- (x[i]-273.15)
}
}
if (from == "F" && to == "K") { # Fahrenheit to Kelvin
for (i in seq_along(x)) {
newX[i] <- ((((x[i]-32)*5)/9) 273.15)
}
}
if (from == "K" && to == "F") { # Kelvin to Fahrenheit
for (i in seq_along(x)) {
newX[i] <- ((((x[i]-273.15)*9)/5) 32)
}
}
return(newX)
}
-testing
> convTemp(c(35,40,45), from="F", to="K")
[1] 274.8167 277.5944 280.3722
CodePudding user response:
Not that you asked, but since @onyambu helped eliminate the for loops, I though I might help eliminate the if statements. I'm not sure if this is more efficient, but I find a bunch of if statements difficult to follow sometimes.
convTemp <- function(x, from = "C", to = "F") {
stopifnot(c(from, to) %in% c('C', 'F', 'K'))
from. <- c(0,-32,-273.15)[which(c('C', 'F', 'K') %in% from)]
to. <- c(0,32,273.15)[which( c('C', 'F', 'K') %in% to)]
mult. <- c(1, 5/9, 9/5 )[sum(which(c(from, to) %in% 'F')) 1]
(x from.)*mult. to.
}
convTemp(c(35,40,45), from="F", to="K")
#> [1] 274.8167 277.5944 280.3722
convTemp(c(35,40,45), from="C", to="F")
#> [1] 95 104 113