简体   繁体   中英

Changing entries in a dataframe depending on whether they are between two values or below a value

I have a dataframe with distance in one column and scores in another column, eg

Distance Scores
1000.    1
1500.    1

etc.

I have a piecewise function that says: If Distance >= 1000, change Scores to zero If Distance is between 300 and 1000, change score to 0.5(1000 - the distance value) If Distance is less than 300, change to 0.5(1000-300)

I tried the following:

DF$Scores[DF$Distance>=1000] <- 0
DF$Scores[DF$Distance>300 & DF$Distance<1000] <-0.5(1000-DF$Distance)
DF$Scores[DF$Distance<=300]<- 0.5*(1000 -300 )

However, this is not working because the Scores that have been changed to zero are then later altered by the less than 300 condition. Also, the replacement of the scoring values for distances between 300 to 1000 gives 'Error:attempt to apply non-function'.

I would suggest an approach like this:

#Data
df <- structure(list(Distance = c(1000, 1500), Scores = c(1L, 1L)), class = "data.frame", row.names = c(NA, 
-2L))

The code:

df$Scores <- ifelse(df$Distance>=1000,0,
                    ifelse(df$Distance>300 & df$Distance<1000,0.5*(1000-df$Distance),
                           ifelse(df$Distance<=300,0.5*(1000 -300 ),NA)))

Output:

  Distance Scores
1     1000      0
2     1500      0

Just be careful, if you have many conditions nesting ifelse can be complex.

Adding the other cases that might occur and providing a dplyr solution which is sometimes easier for humans to read...

df <- structure(list(Distance = c(1000, 1500, 500, 250), 
                     Scores = c(1L, 1L, 2L, 3L)), 
                     class = "data.frame", 
                     row.names = c(NA, -4L))
library(dplyr)

df %>%
   mutate(Scores = case_when(
      Distance >= 1000 ~ 0,
      Distance < 1000 & Distance > 300 ~ .5 * (1000 - Distance),
      Distance <= 300 ~ 0.5 * (1000 - 300),
      TRUE ~ as.numeric(Scores)
   ))

#>   Distance Scores
#> 1     1000      0
#> 2     1500      0
#> 3      500    250
#> 4      250    350

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM