Logistic Regression: Error Computation failed in `stat_smooth()`: y values must be 0 <= y <= 1

Viewed 1144

I am trying to run a logistic regression plot with a binomial log regression line and I keep getting the following warning message:

geom_smooth()` using formula 'y ~ x' Warning message:
Computation failed in `stat_smooth()`: y values must be 0 <= y <= 1

My code is:

library(ggplot2)
ggplot(dataq, aes(meanst,FamFriend3b)) + 
  geom_point() +
  geom_smooth( method = "glm", se = FALSE, method.args = list(family = "binomial"))

Thus I am unable to plot the line. (I do get the graph still)

Click Here for Plot

I've set my variables to factors with two levels.

 [1] 0 0 0 0 0 1 0 1 1 1 0 1 0 1 0 0 0 1
Levels: 0 1

...
 $ meanst         : num [1:18] 457 475 384 100 195 ...
 $ CovidDx1       : Factor w/ 1 level "0": 1 1 1 1 1 1 1 1 1 1 ...
 $ CovidExposure2 : Factor w/ 1 level "0": 1 1 1 1 1 1 1 1 1 1 ...
 $ KnowAny3a      : Factor w/ 2 levels "0","1": 1 1 2 1 2 2 2 2 2 2 ...
 $ FamFriend3b    : Factor w/ 2 levels "0","1": 1 1 1 1 1 2 1 2 2 2 ...

How do I fix this error??? Any help would be appreciated!

2 Answers

You don't convert your column to a factor of 0,1 . You should keep it as an integer.

Let's say your data is something like this:

set.seed(111)
dataq = data.frame(meanst = rnorm(50,rep(1:2,each=25),0.5),
FamFriend3b = rbinom(50,1,rep(c(0.2,0.8),each=25)))

dataq$FamFriend3b = factor(dataq$FamFriend3b)

str(dataq)
'data.frame':   50 obs. of  2 variables:
 $ meanst     : num  1.118 0.835 0.844 -0.151 0.915 ...
 $ FamFriend3b: Factor w/ 2 levels "0","1": 1 1 2 1 2 1 1 1 1 2 ...

FamFriend3b is 0,1 encoded as a factor. When plotting it converts to 1,2 which makes it problematic. For plotting, you can either force it to 0/1 on the fly:

library(ggplot2)
ggplot(dataq, aes(meanst,as.numeric(FamFriend3b) - 1)) + 
geom_point() +
geom_smooth( method = "glm", se = FALSE, method.args = list(family = "binomial"))

enter image description here

Or if you make a integer column on the fly:

ggplot(dataq, aes(meanst,as.numeric(as.character(FamFriend3b)))) + 
    geom_point() +
    geom_smooth( method = "glm", se = FALSE, method.args = list(family = "binomial"))

Factor conversion to numeric values can be counter-intuitive:

as.numeric(factor(c(0, 1)))
# 1 2
as.numeric(factor(c(0, 15))
# 1 2
as.numeric(factor(c("foo", "bar")))
# 2 1

What happens is that the numeric values are transformed into character levels of the factor, and as.numeric will number the levels in alphabetical order starting at 1.

In your case, if you let geom_smooth perform the conversion, you will not have the expected {0, 1} values, thus you have to perform the conversion manually prior to your code with:

dataq$FamFriend3b <- as.numeric(as.character(dataq$FamFriend3b))
# Or with slightly better performance, see below: 
dataq$FamFriend3b <- as.numeric(levels(dataq$FamFriend3b))[dataq$FamFriend3b]

EDIT: after a glance at ?factor, I updated the answer to use the recommended way of conversion:

To transform a factor f to approximately its original numeric values, as.numeric(levels(f))[f] is recommended and slightly more efficient than as.numeric(as.character(f)).

Related