R使用多个ifelse语句进行sapply / lapply

时间:2017-07-07 20:55:23

标签: r if-statement lapply sapply

我正在尝试使用sapply或lapply简化以下多个ifelse代码(仍无法区分它们)。

我的目标是根据展示位置分配积分,如下所示。

df$Point <- ifelse(df$Placement_v2 <= 1, 10,
ifelse(df$Placement_v2 <= 10, 9, 
ifelse(df$Placement_v2 <= 25, 8,
ifelse(df$Placement_v2 <= 50, 7, 1) )))

这段代码工作正常,但我想使用sapply或lapply(或任何其他函数)创建一个数据帧,而只是上面的代码。

我已尝试过此代码,但未按预期工作。只有位置1的行得到10分,其他行最终得1。

&lt;第二代码&gt;

df$Point <- sapply(df2$Placement, function(x) ifelse(df$Placement_v2 <= x, df2$Point[df2$Placement == x], 1 ) )

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

有几种方法可以解决这个问题。我将使用data.table

library(data.table)

set.seed(123)
df <- data.table(Placement_v2 = runif(200, -10, 100))

第一个选项,将评估结果移至某个函数,然后将lapply函数移至Placement_v2列。这样做的好处是比嵌套的ifelse语句更清晰。

funky <- function(x) {

  if (x <= 1) {
    val <- 10
  } else if (x <= 10){
    val <- 9
  } else if (x <= 25){
    val <- 8
  } else if (x <= 50){
    val <- 7
  } else {
    val <- 1
  }

  return(val)

}

df[, Point := unlist(lapply(Placement_v2, funky))]

结果:

     Placement_v2 Point
  1:    21.633527     8
  2:    76.713565     1
  3:    34.987461     7
  4:    87.131914     1
  5:    93.451401     1
 ---                   
196:    41.318597     7
197:    34.751585     7
198:    62.515336     1
199:     6.758128     9
200:    53.015376     1

我会通过对数据进行子集化并按每个子集进行分配来实现此目的。您可以通过指定每个子集df[Placement_v2 <= 1]df[Placement_v2 >= 1 & Placement_v2 <= 10]等来执行此操作。但是,如果按正确顺序执行此操作,则可以避免双重等式评估。

df[, Point := 1]
df[Placement_v2 <= 50, Point := 7]
df[Placement_v2 <= 25, Point := 8]
df[Placement_v2 <= 10, Point := 9]
df[Placement_v2 <=  1, Point := 10]

结果相同:

     Placement_v2 Point
  1:    21.633527     8
  2:    76.713565     1
  3:    34.987461     7
  4:    87.131914     1
  5:    93.451401     1
 ---                   
196:    41.318597     7
197:    34.751585     7
198:    62.515336     1
199:     6.758128     9
200:    53.015376     1

答案 1 :(得分:0)

您可以使用值和替换创建数据框。然后,您可以使用cut查找适当的值

dict = data.frame(replacement = c(10, 9, 8, 7, 1, 1),
    values = c(0, 1, 10, 25, 50, 1e5))

#DATA
set.seed(42)
placement = sample(1:100, 15)

cbind(placement,
    new_placement = dict$replacement[as.integer(cut(placement, breaks = dict$values))])
#     placement new_placement
# [1,]        92             1
# [2,]        93             1
# [3,]        29             7
# [4,]        81             1
# [5,]        62             1
# [6,]        50             7
# [7,]        70             1
# [8,]        13             8
# [9,]        61             1
#[10,]        65             1
#[11,]        42             7
#[12,]        91             1
#[13,]        83             1
#[14,]        23             8
#[15,]        40             7