首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >针对多个类别的ifelse风格重新编码的习惯用法

针对多个类别的ifelse风格重新编码的习惯用法
EN

Stack Overflow用户
提问于 2012-05-03 20:29:07
回答 13查看 2.9K关注 0票数 17

我经常遇到这种情况,因此我认为必须有一个很好的习语来描述它。假设我有一个具有一系列属性的data.frame,包括“产品”。我也有一个钥匙,将产品转换为品牌+大小。产品代码1-3是Tylenol,4-6是Advil,7-9是Bayer,10-12是通用的。

对此进行编码的最快方法(就人类时间而言)是什么?

如果有3个或更少的类别,我倾向于使用嵌套的ifelse,如果有3个以上的类别,我倾向于输入数据表并将其合并。还有更好的想法吗? Stata有一个非常好的recode command,用于这类事情,尽管我认为它促进了数据和代码的混合。

代码语言:javascript
复制
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")
EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2012-05-03 20:53:42

可以使用列表作为关联数组来定义brand -> product code映射,即:

代码语言:javascript
复制
brands <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)

一旦你有了它,你可以反转它来创建一个product code -> brand列表(可能会占用很多内存),或者直接使用一个搜索函数:

代码语言:javascript
复制
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循环让我很烦!),但至少它是矢量化的,所以它只需要一次遍历列表。

使用它的过程类似于:

代码语言:javascript
复制
> 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   Bayer

recodelevels<-解决方案非常好,但它们也比这个解决方案慢得多(一旦有了find.key,这对人类来说就比recode更容易了,与levels<-不相上下):

代码语言:javascript
复制
> 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解决方案更不适合人类。)

票数 14
EN

Stack Overflow用户

发布于 2012-05-03 21:19:39

您可以将您的变量转换为因子,并通过levels<-函数更改其级别。在一个命令中,它可能是这样的:

代码语言:javascript
复制
`levels<-`(
    factor(dat$product),
    list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
)

在步骤中:

代码语言:javascript
复制
brands <- factor(dat$product)
levels(brands) <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
票数 19
EN

Stack Overflow用户

发布于 2012-05-03 21:09:26

我喜欢car包中的recode函数:

代码语言:javascript
复制
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   Bayer
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10431403

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档