我经常遇到这种情况,因此我认为必须有一个很好的习语来描述它。假设我有一个具有一系列属性的data.frame,包括“产品”。我也有一个钥匙,将产品转换为品牌+大小。产品代码1-3是Tylenol,4-6是Advil,7-9是Bayer,10-12是通用的。
对此进行编码的最快方法(就人类时间而言)是什么?
如果有3个或更少的类别,我倾向于使用嵌套的ifelse,如果有3个以上的类别,我倾向于输入数据表并将其合并。还有更好的想法吗? Stata有一个非常好的recode command,用于这类事情,尽管我认为它促进了数据和代码的混合。
dat <- structure(list(product = c(11L, 11L, 9L, 9L, 6L, 1L, 11L, 5L,
7L, 11L, 5L, 11L, 4L, 3L, 10L, 7L, 10L, 5L, 9L, 8L)), .Names = "product", row.names = c(NA,
-20L), class = "data.frame")发布于 2012-05-03 20:53:42
可以使用列表作为关联数组来定义brand -> product code映射,即:
brands <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)一旦你有了它,你可以反转它来创建一个product code -> brand列表(可能会占用很多内存),或者直接使用一个搜索函数:
find.key <- function(x, li, default=NA) {
ret <- rep.int(default, length(x))
for (key in names(li)) {
ret[x %in% li[[key]]] <- key
}
return(ret)
}我确信有更好的方法来编写这个函数( for循环让我很烦!),但至少它是矢量化的,所以它只需要一次遍历列表。
使用它的过程类似于:
> dat$brand <- find.key(dat$product, brands)
> dat
product brand
1 11 Generic
2 11 Generic
3 9 Bayer
4 9 Bayer
5 6 Advil
6 1 Tylenol
7 11 Generic
8 5 Advil
9 7 Bayer
10 11 Generic
11 5 Advil
12 11 Generic
13 4 Advil
14 3 Tylenol
15 10 Generic
16 7 Bayer
17 10 Generic
18 5 Advil
19 9 Bayer
20 8 Bayerrecode和levels<-解决方案非常好,但它们也比这个解决方案慢得多(一旦有了find.key,这对人类来说就比recode更容易了,与levels<-不相上下):
> microbenchmark(
recode=recode(dat$product,recodes="1:3='Tylenol';4:6='Advil';7:9='Bayer';10:12='Generic'"),
find.key=find.key(dat$product, brands),
levels=`levels<-`(factor(dat$product),brands))
Unit: microseconds
expr min lq median uq max
1 find.key 64.325 69.9815 76.8950 83.8445 221.748
2 levels 240.535 248.1470 274.7565 306.8490 1477.707
3 recode 1636.039 1683.4275 1730.8170 1855.8320 3095.938(我无法正确地对switch版本进行基准测试,但它似乎比上面的所有版本都要快,尽管它比recode解决方案更不适合人类。)
发布于 2012-05-03 21:19:39
您可以将您的变量转换为因子,并通过levels<-函数更改其级别。在一个命令中,它可能是这样的:
`levels<-`(
factor(dat$product),
list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
)在步骤中:
brands <- factor(dat$product)
levels(brands) <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)发布于 2012-05-03 21:09:26
我喜欢car包中的recode函数:
library(car)
dat$brand <- recode(dat$product,
recodes="1:3='Tylenol';4:6='Advil';7:9='Bayer';10:12='Generic'")
# > dat
# product brand
# 1 11 Generic
# 2 11 Generic
# 3 9 Bayer
# 4 9 Bayer
# 5 6 Advil
# 6 1 Tylenol
# 7 11 Generic
# 8 5 Advil
# 9 7 Bayer
# 10 11 Generic
# 11 5 Advil
# 12 11 Generic
# 13 4 Advil
# 14 3 Tylenol
# 15 10 Generic
# 16 7 Bayer
# 17 10 Generic
# 18 5 Advil
# 19 9 Bayer
# 20 8 Bayerhttps://stackoverflow.com/questions/10431403
复制相似问题