R中的数据转换:更好地在行值或因子级别上操作?

R中的数据转换:更好地在行值或因子级别上操作?,r,R,假设你注意到因子大向量中的一些值是相似的。巩固这些价值观的更好策略是什么?我在分析中使用了两种策略,这两种策略在性能上似乎具有可比性。1,将合并逻辑放入函数中并使用sapply,2,更改因子级别本身。下面我给出了每种方法的一个示例 示例1,将合并逻辑放入函数中并使用sapply: favorite.color <- c('yellow', 'banana', 'canary yellow', 'aqua', 'blue') messy.vector.of.favorite.colors &

假设你注意到因子大向量中的一些值是相似的。巩固这些价值观的更好策略是什么?我在分析中使用了两种策略,这两种策略在性能上似乎具有可比性。1,将合并逻辑放入函数中并使用
sapply
,2,更改因子级别本身。下面我给出了每种方法的一个示例

示例1,将合并逻辑放入函数中并使用
sapply

favorite.color <- c('yellow', 'banana', 'canary yellow', 'aqua', 'blue')
messy.vector.of.favorite.colors <- as.factor(sample(favorite.color, 10000, replace=TRUE))

consolidate.colors <- function(color) {
     if(color == 'banana') {
         return('yellow')
     }
     if(color == 'canary yellow') {
         return('yellow')
     }
     if(color == 'aqua') {
         return('blue')
     }
     else {
         return(color)
     }
}

clean.colors <- as.factor(sapply(as.character(messy.vector.of.favorite.colors), consolidate.colors, USE.NAMES=FALSE))
# Gives factor vector with two levels: blue, yellow
favorite.color您可以使用类似于python dict的“查找”列表:

z <- list(yellow = "yellow", banana = "yellow", 'canary yellow' = "yellow", aqua = "blue", blue = "blue")

clean.colors <- factor(unlist(z[messy.vector.of.favorite.colors]))

因此,更改级别是最快的。

最有效的方法是修改级别。您可以将代码替换为:

levels(working.vector) <- list(yellow = c("yellow", "banana", "canary yellow"), 
                               blue = c("blue", "aqua"))

levels(working.vector)在我处理此类因素的经验中,这是一种痛苦。我会尝试转换为字符串,进行字符串替换,然后转换回因子。但是,如果你有数百个因素,这会变得单调乏味。在这种情况下,我会使用查找表。在我学会如何操作关卡之前,我同意你的看法。很多关于因子的操作实际上都归结为改变水平,这其实很容易。处理字符串效率很低,我建议尽可能避免使用它们。
library(microbenchmark)
microbenchmark(sapply = as.factor(sapply(as.character(messy.vector.of.favorite.colors), consolidate.colors, USE.NAMES=FALSE)),
               vectorized = {working.vector <- messy.vector.of.favorite.colors;
               levels(working.vector)[levels(working.vector) == 'banana'] <- 'yellow'
               levels(working.vector)[levels(working.vector) == 'canary yellow'] <- 'yellow'
               levels(working.vector)[levels(working.vector) == 'aqua'] <- 'blue'},
               dict =  factor(unlist(z[messy.vector.of.favorite.colors])),
               changelevels = levels(working.vector) <- list(yellow = c("yellow", "banana", "canary yellow"), 
                                                             blue = c("blue", "aqua")))

Unit: microseconds
         expr       min        lq       mean     median         uq       max neval
       sapply 53521.510 54231.525 57616.0458 54751.2690 55839.3330 78979.161   100
   vectorized  1373.568  1427.713  1498.3758  1458.6240  1522.1765  2021.760   100
         dict  6284.542  6338.110  6488.8144  6395.7090  6546.4300  8763.261   100
 changelevels   511.489   544.897   581.3997   566.4005   588.4805   842.113   100
levels(working.vector) <- list(yellow = c("yellow", "banana", "canary yellow"), 
                               blue = c("blue", "aqua"))