使用条件语句时如何利用 R 向量化? (替代循环)
How to take advantage of R vectorization when using conditional statements? (alternative to looping)
我正在尝试根据数据框中的几个条件对数据进行分组。目前,我正在使用一个效用函数来执行此操作,然后对其进行循环,但由于 R 是矢量化的,我想知道是否有更像 R 的方法来执行此操作?
Items.Ordered <- CMdata$Items.Ordered
orderGroup <- function(Items.Ordered) {
Items.Ordered <- as.numeric(Items.Ordered)
if (CMdata$Items.Ordered == 0) {
return ("NONE")
} else if (CMdata$Items.Ordered > 0 & CMdata$Items.Ordered <= 3) {
return ("SMALL")
} else if (CMdata$Items.Ordered > 3 & CMdata$Items.Ordered <= 8) {
return ("MEDIUM")
} else if (CMdata$Items.Ordered > 8) {
return ("LARGE")
} else {
return ("OTHER")
}
}
Order.Type <- NULL
for (i in 1:nrow(CMdata)) {
Order.Type <- c(Order.Type, orderGroup(CMdata[i,"Items.Orderd"]))
}
CMdata$Order.Type <- as.factor(Order.Type)
我认为您的程序没有按预期运行。
您将单个值传递给 orderGroup
函数,
不是向量,
而且这些条件无论如何都不适用于向量。
我想你真正的意思是这样的:
orderGroup <- function(value) {
if (value == 0) {
"NONE"
} else if (value > 0 & value <= 3) {
"SMALL"
} else if (value > 3 & value <= 8) {
"MEDIUM"
} else if (value > 8) {
"LARGE"
} else {
"OTHER"
}
}
为了让它更实用,
您可以使用 sapply
而不是循环,如下所示:
CMdata$Order.Type <- as.factor(sapply(CMdata$Items.Ordered, orderGroup))
一种可能的解决方案是对您的列执行 cut
,然后根据每个值所属的范围重新标记该因子。例如:
假设您的 CMdata
包含如下列:
CMdata
Items.Ordered
1 NA
2 0
3 1
4 2
5 3
6 4
7 5
8 6
9 7
10 8
11 9
12 10
13 NA
您可以cut
和factor
根据您的情况:
CMdata$Order.Type <- factor(cut(CMdata$Items.Ordered, breaks = c(-Inf, 0, 3, 8, Inf)),
exclude = NULL,
labels = c("NONE", "SMALL", "MEDIUM", "LARGE", "OTHER"))
CMdata
Items.Ordered Order.Type
1 NA OTHER
2 0 NONE
3 1 SMALL
4 2 SMALL
5 3 SMALL
6 4 MEDIUM
7 5 MEDIUM
8 6 MEDIUM
9 7 MEDIUM
10 8 MEDIUM
11 9 LARGE
12 10 LARGE
13 NA OTHER
我正在尝试根据数据框中的几个条件对数据进行分组。目前,我正在使用一个效用函数来执行此操作,然后对其进行循环,但由于 R 是矢量化的,我想知道是否有更像 R 的方法来执行此操作?
Items.Ordered <- CMdata$Items.Ordered
orderGroup <- function(Items.Ordered) {
Items.Ordered <- as.numeric(Items.Ordered)
if (CMdata$Items.Ordered == 0) {
return ("NONE")
} else if (CMdata$Items.Ordered > 0 & CMdata$Items.Ordered <= 3) {
return ("SMALL")
} else if (CMdata$Items.Ordered > 3 & CMdata$Items.Ordered <= 8) {
return ("MEDIUM")
} else if (CMdata$Items.Ordered > 8) {
return ("LARGE")
} else {
return ("OTHER")
}
}
Order.Type <- NULL
for (i in 1:nrow(CMdata)) {
Order.Type <- c(Order.Type, orderGroup(CMdata[i,"Items.Orderd"]))
}
CMdata$Order.Type <- as.factor(Order.Type)
我认为您的程序没有按预期运行。
您将单个值传递给 orderGroup
函数,
不是向量,
而且这些条件无论如何都不适用于向量。
我想你真正的意思是这样的:
orderGroup <- function(value) {
if (value == 0) {
"NONE"
} else if (value > 0 & value <= 3) {
"SMALL"
} else if (value > 3 & value <= 8) {
"MEDIUM"
} else if (value > 8) {
"LARGE"
} else {
"OTHER"
}
}
为了让它更实用,
您可以使用 sapply
而不是循环,如下所示:
CMdata$Order.Type <- as.factor(sapply(CMdata$Items.Ordered, orderGroup))
一种可能的解决方案是对您的列执行 cut
,然后根据每个值所属的范围重新标记该因子。例如:
假设您的 CMdata
包含如下列:
CMdata
Items.Ordered
1 NA
2 0
3 1
4 2
5 3
6 4
7 5
8 6
9 7
10 8
11 9
12 10
13 NA
您可以cut
和factor
根据您的情况:
CMdata$Order.Type <- factor(cut(CMdata$Items.Ordered, breaks = c(-Inf, 0, 3, 8, Inf)),
exclude = NULL,
labels = c("NONE", "SMALL", "MEDIUM", "LARGE", "OTHER"))
CMdata
Items.Ordered Order.Type
1 NA OTHER
2 0 NONE
3 1 SMALL
4 2 SMALL
5 3 SMALL
6 4 MEDIUM
7 5 MEDIUM
8 6 MEDIUM
9 7 MEDIUM
10 8 MEDIUM
11 9 LARGE
12 10 LARGE
13 NA OTHER