Change numeric values ​​in one column based on coefficients in another column

I need to set certain numerical values ​​in one column of my data frame to zero, if in another column they have a certain level of factor.

My dataframe df looks something like this:

Items Store.Type 5 A 4 B 3 C 6 D 3 B 7 E 

I want to make Item = 0, for all lines where Store.Type = "A" or "C"

I am very new to R, but decided it would be a conditional expression of the form β€œIf Store.Type A then Items <- 0” (and then repeat for Store.Type C), but I didn’t understand the page ?"if" at all . I tried:

 df$ItemsFIXED <- with(df, if(Store.Type == "A")Items <-0) 

and received a warning message:

 Warning message: In if (Store.Type2 == "Chain - Brand") Total.generic.items <- 0 : the condition has length > 1 and only the first element will be used` 

So, I noticed here , the following:

  • if is a control flow statement that takes one boolean as an argument
  • ifelse is a vectorized function that takes vectors as all its arguments.

So, assuming that I need ifelse to make the whole column and understand the page ?ifelse , I tried to do "If Store.Type A, then Items <- 0 else do nothing." Actually, I wanted it to be nested, so I tried the following code (now I create a new column so as not to spoil my data, but in the end it will overwrite the Items data)

 df$ItemsFIXED <- with(df, ifelse(Store.Type == "A", Items <-0, ifelse(Store.Type == "C", Items <-0,))) 

and got the following error:

 Error in ifelse(Store.Type2 == "Franchise - Brand", Total.generic.items <- 0, : argument "no" is missing, with no default 

But if I put something for no , it just writes over the correct values. I tried putting Items and Items <- Items in to say "else leave Items as Items", as in the following, but it just changed everything to zero.

 df$ItemsFIXED <- with(df, ifelse(Store.Type == "A", Items <-0, ifelse(Store.Type == "C", Items <-0,Items))) 

Is there a way to tell ifelse do nothing or is there an easier way to do this?

+5
source share
4 answers

Or you can use %in% for multiple match / replace

  df$Items[df$Store.Type %in% c("A", "C")] <- 0 df #Items Store.Type #1 0 A #2 4 B #3 0 C #4 6 D #5 3 B #6 7 E 
+5
source

Using within also an option:

 within(d, Items[Store.Type %in% c("A","C")]<-0) Items Store.Type 1 0 A 2 4 B 3 0 C 4 6 D 5 3 B 6 7 E 
+2
source

Here you can use vectorized replacements. If df is your dataset,

 > df$Items[with(df, Store.Type == "A" | Store.Type == "C")] <- 0L > df # Items Store.Type # 1 0 A # 2 4 B # 3 0 C # 4 6 D # 5 3 B # 6 7 E 

with(df, Store.Type == "A" | Store.Type == "C") returns a logical vector. When a logical vector is placed inside [...] , only TRUE values ​​are returned. Therefore, if we multiply Items with these values, we can replace them with [<-

Also, if you want to use ifelse , you can do something like

 df$Items <- with(df, ifelse(Store.Type == "A" | Store.Type == "C", 0L, Items)) 

or

 within(df, Items <- ifelse(Store.Type == "A" | Store.Type == "C", 0L, Items)) 

but note that ifelse can be very slow from time to time, especially when combined with within and will probably always be slower than the vector up method.

+1
source

Further also works:

 > ddf[ddf$Store.Type=='A'| ddf$Store.Type=='C',]$Items = 0 > ddf Items Store.Type 1 0 A 2 4 B 3 0 C 4 6 D 5 3 B 6 7 E 
+1
source

Source: https://habr.com/ru/post/1202831/


All Articles