69

I have a very basic R question but I am having a hard time trying to get the right answer. I have a data frame that looks like this:

species <- "ABC"
ind <- rep(1:4, each = 24)
hour <- rep(seq(0, 23, by = 1), 4)
depth <- runif(length(ind), 1, 50)
    
df <- data.frame(cbind(species, ind, hour, depth))
df$depth <- as.numeric(df$depth)

What I would like it to select AND replace all the rows where depth < 10 (for example) with zero, but I want to keep all the information associated to those rows and the original dimensions of the data frame.

I have try the following but this does not work.

df[df$depth<10] <- 0 

Any suggestions?

slamballais
  • 3,161
  • 3
  • 18
  • 29
user1626688
  • 1,583
  • 4
  • 18
  • 27
  • 6
    Please abandon the convention of using `data.frame( cbind( ... ) )`. The `cbind` function created a matrix which coerces all of your numeric values to "character". Just use `data.frame(species,ind,hour,depth))`. BTW, This would have worked: `df$depth[df$depth<10] <- 0` – IRTFM Dec 14 '12 at 03:15
  • Thanks for the helpful tip about `cbind()`! I was wondering how one might do `df$depth[df$depth<10] <- 0` in the case where there are `NA` values in the `df$depth` column (which should be ignored)? – Lino Ferreira Jan 25 '21 at 19:05

2 Answers2

118
# reassign depth values under 10 to zero
df$depth[df$depth<10] <- 0

(For the columns that are factors, you can only assign values that are factor levels. If you wanted to assign a value that wasn't currently a factor level, you would need to create the additional level first:

levels(df$species) <- c(levels(df$species), "unknown") 
df$species[df$depth<10]  <- "unknown" 
MattBagg
  • 10,268
  • 3
  • 40
  • 47
  • Would it be possible to adapt this solution to one that can be used on multiple columns at once? I tried `df [ -charcol ] [ df [ -charcol ] < 0] <- NA` But that gave: `Error: cannot allocate vector of size 1.8 Gb`. – Tom Sep 18 '18 at 08:21
  • 4
    Based on @42 solution and the [eth help pages](https://stat.ethz.ch/R-manual/R-devel/library/base/html/Extract.data.frame.html) Try `DF[ ,c(39, 41:42)][DF[ ,c(39, 41:42)] < 0] <- 'NA' ` to replace the values that are less than 0 in the columns 39, 41 and 42 with the string NA – Simone Jan 03 '19 at 10:44
  • This does not work if new value is calcultated from the old one, for example `df$depth[df$depth<10] <- df$depth + 3` – meolic May 07 '21 at 10:42
  • OK, the correct one is `df$depth[df$depth<10] <- (df$depth[df$depth<10] + 3)` – meolic May 07 '21 at 11:01
17

I arrived here from a google search, since my other code is 'tidy' so leaving the 'tidy' way for anyone who else who may find it useful

library(dplyr)
iris %>% 
  mutate(Species = ifelse(as.character(Species) == "virginica", "newValue", as.character(Species)))

stevec
  • 41,291
  • 27
  • 223
  • 311