Defining a custom Error measure (sMAPE) function
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I am defining a custom sMAPE (Symmetric Mean Absolute Percent Error) function in R. I want to add an exception in the code where both actual and predicted are zero.
Here is the sample data:
Actual Predicted
0 0
2 1
1 0
2 4
2 1
1 3
The code is shown below:
sMAAPE <- function(actual, predicted){
if (actual == 0 & predicted == 0){
return(0)
}
else {
output<- mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))
return(output)
}
}
As I mentioned, i want to add an exception, that is wherever both actual and predicted are 0, my error would be zero. The problem with my code is that, when it is encountering both actual and predicted to be 0 in first observation, it is giving the mean error to be zero, but in reality I want mean of all errors.
Can somebody help me with this?
r
add a comment |
I am defining a custom sMAPE (Symmetric Mean Absolute Percent Error) function in R. I want to add an exception in the code where both actual and predicted are zero.
Here is the sample data:
Actual Predicted
0 0
2 1
1 0
2 4
2 1
1 3
The code is shown below:
sMAAPE <- function(actual, predicted){
if (actual == 0 & predicted == 0){
return(0)
}
else {
output<- mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))
return(output)
}
}
As I mentioned, i want to add an exception, that is wherever both actual and predicted are 0, my error would be zero. The problem with my code is that, when it is encountering both actual and predicted to be 0 in first observation, it is giving the mean error to be zero, but in reality I want mean of all errors.
Can somebody help me with this?
r
2
Instead ofif/else
useifelse
with index created usingrowSums
ie.i1 <- !rowSums(df1 != 0); ifelse(i1, 0, othervalue)
Wrap it in a functionsMAAPE <- function(dat) { i1 <- !rowSums(dat !=0); val <- with(dat, mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))); val[i1] <- 0; val}
– akrun
Jan 3 at 9:28
add a comment |
I am defining a custom sMAPE (Symmetric Mean Absolute Percent Error) function in R. I want to add an exception in the code where both actual and predicted are zero.
Here is the sample data:
Actual Predicted
0 0
2 1
1 0
2 4
2 1
1 3
The code is shown below:
sMAAPE <- function(actual, predicted){
if (actual == 0 & predicted == 0){
return(0)
}
else {
output<- mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))
return(output)
}
}
As I mentioned, i want to add an exception, that is wherever both actual and predicted are 0, my error would be zero. The problem with my code is that, when it is encountering both actual and predicted to be 0 in first observation, it is giving the mean error to be zero, but in reality I want mean of all errors.
Can somebody help me with this?
r
I am defining a custom sMAPE (Symmetric Mean Absolute Percent Error) function in R. I want to add an exception in the code where both actual and predicted are zero.
Here is the sample data:
Actual Predicted
0 0
2 1
1 0
2 4
2 1
1 3
The code is shown below:
sMAAPE <- function(actual, predicted){
if (actual == 0 & predicted == 0){
return(0)
}
else {
output<- mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))
return(output)
}
}
As I mentioned, i want to add an exception, that is wherever both actual and predicted are 0, my error would be zero. The problem with my code is that, when it is encountering both actual and predicted to be 0 in first observation, it is giving the mean error to be zero, but in reality I want mean of all errors.
Can somebody help me with this?
r
r
asked Jan 3 at 9:26
SourabhSourabh
93
93
2
Instead ofif/else
useifelse
with index created usingrowSums
ie.i1 <- !rowSums(df1 != 0); ifelse(i1, 0, othervalue)
Wrap it in a functionsMAAPE <- function(dat) { i1 <- !rowSums(dat !=0); val <- with(dat, mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))); val[i1] <- 0; val}
– akrun
Jan 3 at 9:28
add a comment |
2
Instead ofif/else
useifelse
with index created usingrowSums
ie.i1 <- !rowSums(df1 != 0); ifelse(i1, 0, othervalue)
Wrap it in a functionsMAAPE <- function(dat) { i1 <- !rowSums(dat !=0); val <- with(dat, mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))); val[i1] <- 0; val}
– akrun
Jan 3 at 9:28
2
2
Instead of
if/else
use ifelse
with index created using rowSums
ie. i1 <- !rowSums(df1 != 0); ifelse(i1, 0, othervalue)
Wrap it in a function sMAAPE <- function(dat) { i1 <- !rowSums(dat !=0); val <- with(dat, mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))); val[i1] <- 0; val}
– akrun
Jan 3 at 9:28
Instead of
if/else
use ifelse
with index created using rowSums
ie. i1 <- !rowSums(df1 != 0); ifelse(i1, 0, othervalue)
Wrap it in a function sMAAPE <- function(dat) { i1 <- !rowSums(dat !=0); val <- with(dat, mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))); val[i1] <- 0; val}
– akrun
Jan 3 at 9:28
add a comment |
2 Answers
2
active
oldest
votes
Applying @akrun's suggestion in the comments to your problem. I think this is what you need.
# Create a dataset
Actual <- c(0,2,1,2,2,1)
Predicted <- c(0,1,0,4,1,3)
df <- data.frame(cbind(Actual, Predicted))
df
sMAAPE <- function(actual, predicted){
output<- ifelse(actual == 0 & predicted == 0,0, # If actual and predicted are 0, error is 0
abs(actual- predicted)/(abs(actual)+abs(predicted))) # otherwise your function
return(mean(output)) # Return mean of all errors
}
The output:
> sMAAPE(df$Actual, df$Predicted)
[1] 0.4166667
Which is the mean of the following vector [1] 0 0.3333333 1.0000000 0.3333333 0.3333333 0.5000000
You could add na.rm = T
to the mean function so it handles NA's as well.
This is also working. Also, if we add na.rm = T in mean function, this will not consider those NA's at all, therefore the mean would be wrong as the length of df will change after excluding NA's. To deal with this, I used na.rm = T is sum function and then diving this sum with length of dataframe.
– Sourabh
Jan 4 at 11:48
Adding to my previous comment, Here is the code: output_sum<- sum(abs(actual-predicted)/(abs(actual)+abs(predicted)), na.rm = T) output <- output_sum/NROW(actual) return(output)
– Sourabh
Jan 4 at 11:57
add a comment |
The problem is that actual == 0 & predicted == 0
is a logical vector, while if you put a logical vector as the condition of if sentence, only the first element will be judged.
Use sum(abs(actual))+sum(abs(predicted)) == 0
instead in the condition.
This worked. Using sum function allows R to go the else condition. Thanks
– Sourabh
Jan 4 at 11:47
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54019430%2fdefining-a-custom-error-measure-smape-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Applying @akrun's suggestion in the comments to your problem. I think this is what you need.
# Create a dataset
Actual <- c(0,2,1,2,2,1)
Predicted <- c(0,1,0,4,1,3)
df <- data.frame(cbind(Actual, Predicted))
df
sMAAPE <- function(actual, predicted){
output<- ifelse(actual == 0 & predicted == 0,0, # If actual and predicted are 0, error is 0
abs(actual- predicted)/(abs(actual)+abs(predicted))) # otherwise your function
return(mean(output)) # Return mean of all errors
}
The output:
> sMAAPE(df$Actual, df$Predicted)
[1] 0.4166667
Which is the mean of the following vector [1] 0 0.3333333 1.0000000 0.3333333 0.3333333 0.5000000
You could add na.rm = T
to the mean function so it handles NA's as well.
This is also working. Also, if we add na.rm = T in mean function, this will not consider those NA's at all, therefore the mean would be wrong as the length of df will change after excluding NA's. To deal with this, I used na.rm = T is sum function and then diving this sum with length of dataframe.
– Sourabh
Jan 4 at 11:48
Adding to my previous comment, Here is the code: output_sum<- sum(abs(actual-predicted)/(abs(actual)+abs(predicted)), na.rm = T) output <- output_sum/NROW(actual) return(output)
– Sourabh
Jan 4 at 11:57
add a comment |
Applying @akrun's suggestion in the comments to your problem. I think this is what you need.
# Create a dataset
Actual <- c(0,2,1,2,2,1)
Predicted <- c(0,1,0,4,1,3)
df <- data.frame(cbind(Actual, Predicted))
df
sMAAPE <- function(actual, predicted){
output<- ifelse(actual == 0 & predicted == 0,0, # If actual and predicted are 0, error is 0
abs(actual- predicted)/(abs(actual)+abs(predicted))) # otherwise your function
return(mean(output)) # Return mean of all errors
}
The output:
> sMAAPE(df$Actual, df$Predicted)
[1] 0.4166667
Which is the mean of the following vector [1] 0 0.3333333 1.0000000 0.3333333 0.3333333 0.5000000
You could add na.rm = T
to the mean function so it handles NA's as well.
This is also working. Also, if we add na.rm = T in mean function, this will not consider those NA's at all, therefore the mean would be wrong as the length of df will change after excluding NA's. To deal with this, I used na.rm = T is sum function and then diving this sum with length of dataframe.
– Sourabh
Jan 4 at 11:48
Adding to my previous comment, Here is the code: output_sum<- sum(abs(actual-predicted)/(abs(actual)+abs(predicted)), na.rm = T) output <- output_sum/NROW(actual) return(output)
– Sourabh
Jan 4 at 11:57
add a comment |
Applying @akrun's suggestion in the comments to your problem. I think this is what you need.
# Create a dataset
Actual <- c(0,2,1,2,2,1)
Predicted <- c(0,1,0,4,1,3)
df <- data.frame(cbind(Actual, Predicted))
df
sMAAPE <- function(actual, predicted){
output<- ifelse(actual == 0 & predicted == 0,0, # If actual and predicted are 0, error is 0
abs(actual- predicted)/(abs(actual)+abs(predicted))) # otherwise your function
return(mean(output)) # Return mean of all errors
}
The output:
> sMAAPE(df$Actual, df$Predicted)
[1] 0.4166667
Which is the mean of the following vector [1] 0 0.3333333 1.0000000 0.3333333 0.3333333 0.5000000
You could add na.rm = T
to the mean function so it handles NA's as well.
Applying @akrun's suggestion in the comments to your problem. I think this is what you need.
# Create a dataset
Actual <- c(0,2,1,2,2,1)
Predicted <- c(0,1,0,4,1,3)
df <- data.frame(cbind(Actual, Predicted))
df
sMAAPE <- function(actual, predicted){
output<- ifelse(actual == 0 & predicted == 0,0, # If actual and predicted are 0, error is 0
abs(actual- predicted)/(abs(actual)+abs(predicted))) # otherwise your function
return(mean(output)) # Return mean of all errors
}
The output:
> sMAAPE(df$Actual, df$Predicted)
[1] 0.4166667
Which is the mean of the following vector [1] 0 0.3333333 1.0000000 0.3333333 0.3333333 0.5000000
You could add na.rm = T
to the mean function so it handles NA's as well.
edited Jan 3 at 10:29
answered Jan 3 at 10:22
NiekNiek
974518
974518
This is also working. Also, if we add na.rm = T in mean function, this will not consider those NA's at all, therefore the mean would be wrong as the length of df will change after excluding NA's. To deal with this, I used na.rm = T is sum function and then diving this sum with length of dataframe.
– Sourabh
Jan 4 at 11:48
Adding to my previous comment, Here is the code: output_sum<- sum(abs(actual-predicted)/(abs(actual)+abs(predicted)), na.rm = T) output <- output_sum/NROW(actual) return(output)
– Sourabh
Jan 4 at 11:57
add a comment |
This is also working. Also, if we add na.rm = T in mean function, this will not consider those NA's at all, therefore the mean would be wrong as the length of df will change after excluding NA's. To deal with this, I used na.rm = T is sum function and then diving this sum with length of dataframe.
– Sourabh
Jan 4 at 11:48
Adding to my previous comment, Here is the code: output_sum<- sum(abs(actual-predicted)/(abs(actual)+abs(predicted)), na.rm = T) output <- output_sum/NROW(actual) return(output)
– Sourabh
Jan 4 at 11:57
This is also working. Also, if we add na.rm = T in mean function, this will not consider those NA's at all, therefore the mean would be wrong as the length of df will change after excluding NA's. To deal with this, I used na.rm = T is sum function and then diving this sum with length of dataframe.
– Sourabh
Jan 4 at 11:48
This is also working. Also, if we add na.rm = T in mean function, this will not consider those NA's at all, therefore the mean would be wrong as the length of df will change after excluding NA's. To deal with this, I used na.rm = T is sum function and then diving this sum with length of dataframe.
– Sourabh
Jan 4 at 11:48
Adding to my previous comment, Here is the code: output_sum<- sum(abs(actual-predicted)/(abs(actual)+abs(predicted)), na.rm = T) output <- output_sum/NROW(actual) return(output)
– Sourabh
Jan 4 at 11:57
Adding to my previous comment, Here is the code: output_sum<- sum(abs(actual-predicted)/(abs(actual)+abs(predicted)), na.rm = T) output <- output_sum/NROW(actual) return(output)
– Sourabh
Jan 4 at 11:57
add a comment |
The problem is that actual == 0 & predicted == 0
is a logical vector, while if you put a logical vector as the condition of if sentence, only the first element will be judged.
Use sum(abs(actual))+sum(abs(predicted)) == 0
instead in the condition.
This worked. Using sum function allows R to go the else condition. Thanks
– Sourabh
Jan 4 at 11:47
add a comment |
The problem is that actual == 0 & predicted == 0
is a logical vector, while if you put a logical vector as the condition of if sentence, only the first element will be judged.
Use sum(abs(actual))+sum(abs(predicted)) == 0
instead in the condition.
This worked. Using sum function allows R to go the else condition. Thanks
– Sourabh
Jan 4 at 11:47
add a comment |
The problem is that actual == 0 & predicted == 0
is a logical vector, while if you put a logical vector as the condition of if sentence, only the first element will be judged.
Use sum(abs(actual))+sum(abs(predicted)) == 0
instead in the condition.
The problem is that actual == 0 & predicted == 0
is a logical vector, while if you put a logical vector as the condition of if sentence, only the first element will be judged.
Use sum(abs(actual))+sum(abs(predicted)) == 0
instead in the condition.
answered Jan 3 at 9:43
XinzXinz
543
543
This worked. Using sum function allows R to go the else condition. Thanks
– Sourabh
Jan 4 at 11:47
add a comment |
This worked. Using sum function allows R to go the else condition. Thanks
– Sourabh
Jan 4 at 11:47
This worked. Using sum function allows R to go the else condition. Thanks
– Sourabh
Jan 4 at 11:47
This worked. Using sum function allows R to go the else condition. Thanks
– Sourabh
Jan 4 at 11:47
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54019430%2fdefining-a-custom-error-measure-smape-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Instead of
if/else
useifelse
with index created usingrowSums
ie.i1 <- !rowSums(df1 != 0); ifelse(i1, 0, othervalue)
Wrap it in a functionsMAAPE <- function(dat) { i1 <- !rowSums(dat !=0); val <- with(dat, mean(abs(actual-predicted)/(abs(actual)+abs(predicted)))); val[i1] <- 0; val}
– akrun
Jan 3 at 9:28