R sapply/lapply 带有多个 ifelse 语句
R sapply/lapply with multiple ifelse statements
我正在尝试使用 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 结束。
<第二个代码>
df$Point <- sapply(df2$Placement, function(x) ifelse(df$Placement_v2 <= x, df2$Point[df2$Placement == x], 1 ) )
我该如何解决这个问题?
您可以创建一个包含值和替换项的数据框。然后你可以使用 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
解决此问题的几种方法。我将使用 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
我正在尝试使用 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 结束。
<第二个代码>
df$Point <- sapply(df2$Placement, function(x) ifelse(df$Placement_v2 <= x, df2$Point[df2$Placement == x], 1 ) )
我该如何解决这个问题?
您可以创建一个包含值和替换项的数据框。然后你可以使用 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
解决此问题的几种方法。我将使用 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