0

On R: I have a dataset of 150 000 obs. of 645 variables. I need to convert all negative value of the dataset (645 columns) by a formula. Some column are string but most of the variables are numeric. Like: if value positive, stay the same AND if its negative i want to apply this formula (value *-1)/2

My dataset name is sed_lac_qc: I tried this:

if (sed_lac_qc<0 {sed_lac_qc=((sed_lac_qc*-1)/2)} else {sed_lac_qc=sed_lac_qc}

but it make this error: Warning message: In if (sed_lac_qc < 0) { : the condition has length > 1 and only the first element will be used

guall28
  • 1
  • 1
  • [See here](https://stackoverflow.com/q/5963269/5325862) on making a reproducible example that is easier for folks to help with. – camille Nov 12 '21 at 18:49

3 Answers3

1

Assume that we have a data frame in which every column is numeric. For example assume the data frame, BOD2, defined in the Note at the end based on the BOD data frame that comes with R.

1) lapply Then for each column perform the operation creating a list of columns and convert it back into a data frame. We can replace the indicated function with any other function as long as it represents an operation which is vectorized in R.

No packages are used.

as.data.frame(lapply(BOD2, function(x) ifelse(x > 0, x, -x/2)))

giving:

  Time demand
1  0.5    8.3
2  0.5   10.3
3  3.0   19.0
4  4.0   16.0
5  5.0   15.6
6  7.0   19.8

If there are non-numeric columns then use:

as.data.frame(lapply(BOD2, function(x) {
  if (is.numeric(x)) ifelse(x > 0, x, -x/2) else x
}))

2) pmax Alternately for this particular transformation we can use pmax giving the same result.

pmax(BOD2, -BOD2/2)

or if there are non-numeric columns then

is_num <- sapply(BOD2, is.numeric)
BOD3 <- BOD2[is_num]
replace(BOD2, is_num, pmax(BOD3, -BOD3/2))

3) dplyr Using dplyr we can do this:

library(dplyr)
BOD2 %>% mutate(across(where(is.numeric), ~ ifelse(. > 0, ., -./2)))

4) collapse We can use ftransformv from the collapse package:

library(collapse)
ftransformv(BOD2, is.numeric, function(x) ifelse(x > 0, x, -x/2))

Note

BOD2 <- BOD
BOD2[1:2, 1] <- -1

so BOD2 looks like this:

  Time demand
1   -1    8.3
2   -1   10.3
3    3   19.0
4    4   16.0
5    5   15.6
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
0

As you have mentioned that you want to find out negative value from a data set and then want to convert negative value by a formula. If you have shared your code that you tried to solve this problem, then it will be clear to us that in which level you have reached. Moreover, I'm giving you a simple solution to this problem.

    if(value < 0){
        value = (value *-1)/2
    }else{
        value = value
    }

or try ifelse

ifelse(test, yes, no)

like:

ifelse(sed_lac_qc<0, (sed_lac_qc*-1)/2, sed_lac_qc)

Try to check your value is smaller than 0, if smaller than 0, then apply your formula.

  • Thanks, but It return: Warning message: In if (sed_lac_qc < 0) { : the condition has length > 1 and only the first element will be used – guall28 Nov 12 '21 at 18:41
  • 1
    @guall28 Could you provide an example code for us to look at (see the suggestion for reprex)? It is really hard to help without some idea of what you are trying to achieve. – Harunur Rashid Nov 12 '21 at 18:45
  • @guall28 you are trying to pass f() a vector of length > 1. if() and else can only react to one logical element (i.e., a TRUE or a FALSE) at a time. You should either use sapply(t, f), or use ifelse(). ifelse() can respond to a logical vector with length greater than one. First, you should make sure you are intending to pass f() a vector of length > 1. If you are, then write your function using ifelse(): ifelse(condition, do_if_true, do_if_false) – Harunur Rashid Nov 12 '21 at 18:49
  • @guall28 use ifelse(condition, do_if_true, do_if_false) may be help you – Harunur Rashid Nov 12 '21 at 18:51
  • @HarunurRashid Your ifelse is incorrect. You cannot do that – Onyambu Nov 12 '21 at 18:57
  • Onyambu - What would be a correct ifelse?? – guall28 Nov 12 '21 at 19:10
  • @Onyambu here is that ifelse statement manual link: https://www.datamentor.io/r-programming/ifelse-function/ – Harunur Rashid Nov 12 '21 at 19:11
  • @HarunurRashid *your statement is incorrect.* for me to make that claim means I do understand the use of the vectorized ifelse function. Its parameters are `test, yes, no` and not what you have. – Onyambu Nov 12 '21 at 19:14
  • @Onyambu statement updated – Harunur Rashid Nov 12 '21 at 19:22
  • You did not have to use `yes, no` in function. Those are the parameters, not the arguments. You should replace the yes no with the appropriate arguments. You reviously had `sed_lac_qc=...` within the `ifelse` function. You cannot have that – Onyambu Nov 12 '21 at 19:22
  • previously you had `ifelse(sed_lac_qc<0, sed_lac_qc=((sed_lac_qc*-1)/2), sed_lac_qc=sed_lac_qc)` but this is incorrect. It cannot run, you should rather have `ifelse(sed_lac_qc<0,yes = (sed_lac_qc*-1)/2, no=sed_lac_qc)` If you truly have to name the arguments or you should just have `ifelse(sed_lac_qc<0, (sed_lac_qc*-1)/2, sed_lac_qc)` – Onyambu Nov 12 '21 at 19:25
  • @Onyambu Here shows me the solution for the warning message: the condition has length > 1 and only the first element will be used. https://community.rstudio.com/t/the-condition-has-length-1-and-only-the-first-element-will-be-used/16737/3 – Harunur Rashid Nov 12 '21 at 19:25
  • What with the warning? the warning is when using `if else` conditions and not the `ifelse` function. `ifelse` function is vectorized hence no warning. – Onyambu Nov 12 '21 at 19:27
0

Since you have a whole dataframe as numeric. Just do a mathematical computation on it:

sg <- df > 0
df1 <- df^sg * (-df/2)^(1-sg)

Another option is to use the ifelse:

data.frame(ifelse(df > 0, df, -df/2))
Onyambu
  • 67,392
  • 3
  • 24
  • 53
  • Thanks! What if i have some string variables in my dataset? – guall28 Nov 12 '21 at 19:26
  • @guall28 you specifically mentioned that you had numeric variables. If you have strings, you will have to select the numerics and work with them. `df %>%mutate(across(where(is.numerc), ~ifelse(x>0, x, -x/2)))` – Onyambu Nov 12 '21 at 19:29