2

I went through similar questions but I still could not sort my problem out. Anyway, I have a data-frame (size:36*42) that contains numbers while in the last row (36'th row) it has the dates for each column. I wanted to normalize the columns of this data-frame (the whole data-frame except the last row) using the following function:

normalize<-function(x){return((x-min(x, na.rm=TRUE))/(max(x, na.rm=TRUE)-min(x, na.rm=TRUE)))}

but I always get this error:

Error in x - min(x, na.rm = TRUE) : non-numeric argument to binary operator

The thing that I have tried

as.data.frame(lapply(df[c(1:nrow(df)-1),], normalize))

BTW, when I check the typeof(df) it shows that the df is a list but when I check it using is.list(df)->TRUE and also is.data.frame(df)->TRUE, which it makes me confuse.

Thanks

Ester Silva
  • 670
  • 6
  • 24
  • 2
    You have some factors or characters in there. Try `sapply(df,class)`. You should provide sample data with `dput`. Did you type this as is `is.list(df)->TRUE`? – NelsonGon May 03 '19 at 11:07
  • 1
    regarding your question about your `data.frame` having a `list` type, take a look at [this](https://stackoverflow.com/questions/6258004/types-and-classes-of-variables) post. – patL May 03 '19 at 11:10
  • @NelsonGon, Yes – Ester Silva May 03 '19 at 11:14
  • 1
    @NelsonGon, "Did you type this as is is.list(df)->TRUE?", Yes – Ester Silva May 03 '19 at 11:18
  • Also, I am trying to extract the data to upload it here – Ester Silva May 03 '19 at 11:18
  • If you just want to calculate on the `numeric`s, maybe simply do: `normalize<-function(x){ x<-Filter(is.numeric,x) return( (x-min(x, na.rm=TRUE)) / (max(x, na.rm=TRUE)-min(x, na.rm=TRUE))) }`? – NelsonGon May 03 '19 at 11:41

2 Answers2

1

The issue has to do with variable class. Check the class - class( mtcars$mpg ) . This function will convert your cols to numeric

normalize<-function(x){

x <- as.numeric( as.character( x ))

y <- (x-min(x, na.rm=TRUE))/
    (max(x, na.rm=TRUE)-min(x, na.rm=TRUE))

return(y)

}

It works see: normalize( mtcars$mpg ) normalize( as.character( mtcars$mpg ))

You can add to your dataframe

mtcars$newvar <- normalize( mtcars$mpg ) 

or do several cols

mtcars[ , 3:7]<- sapply( mtcars[ , 3:7], normalize )
MatthewR
  • 2,660
  • 5
  • 26
  • 37
1

You can parse your normalize function through only numeric variables with mutate_if from dplyr.

 library(dplyr)

normalize<-function(x){
 return( (x-min(x, na.rm=TRUE)) / (max(x, na.rm=TRUE)-min(x, na.rm=TRUE)))
}

df %>%
   mutate_if(is.numeric, normalize)

Since you didn't provide a sample from your data, using iris dataset it would be something like:

iris %>% 
  mutate_if(is.numeric, normalize)

and the output would be (first ten rows):

#Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
#1     0.22222222  0.62500000   0.06779661  0.04166667     setosa
#2     0.16666667  0.41666667   0.06779661  0.04166667     setosa
#3     0.11111111  0.50000000   0.05084746  0.04166667     setosa
#4     0.08333333  0.45833333   0.08474576  0.04166667     setosa
#5     0.19444444  0.66666667   0.06779661  0.04166667     setosa
#6     0.30555556  0.79166667   0.11864407  0.12500000     setosa
#7     0.08333333  0.58333333   0.06779661  0.08333333     setosa
#8     0.19444444  0.58333333   0.08474576  0.04166667     setosa
#9     0.02777778  0.37500000   0.06779661  0.04166667     setosa
#10    0.16666667  0.45833333   0.08474576  0.00000000     setosa
NelsonGon
  • 13,015
  • 7
  • 27
  • 57
patL
  • 2,259
  • 1
  • 17
  • 38