【问题标题】:add factor levels that are not in use添加未使用的因子水平
【发布时间】:2020-01-02 18:51:35
【问题描述】:

我有一个无法解决的简单问题: 我想绘制带有因子的data.frame(一个月),其中有时缺少水平。 R 属性只有现有的级别,所以如果存在一个、两个或更多级别,我的图会有所不同。

这里是一个例子:

    library(ggplot2)
    library(reshape2)

f             <- factor(c("Free", "Work"))
mon           <- as.data.frame(matrix(as.factor(rep(f[2], times = 8)), nrow = 4)) 
colnames(mon) <- c("A", "B")

mt    <- t(as.matrix(rev(data.frame(as.matrix(mon))))) #  change order of y
m     <- melt(mt)

col   <- c("azure",  "orange")

ggplot(m, aes(x = Var2, y = Var1, fill = value)) +
  geom_tile(colour="grey10") +
  scale_fill_manual(values = col, labels = f, name = NULL) +
  theme(panel.background = element_rect(fill = "white"), axis.ticks = element_blank()) +
  theme(axis.title.x = element_blank(), axis.title.y = element_blank()) 

如您所见,我将 2 个因素的第二个元素“工作”归因于元素,但它绘制了“免费”。令人不安的是,mon 的因子只有 1 个级别,而不是 2 个可能的级别。 如果我将多个级别归因于mon,它会给出另一个情节:

mon   <- as.data.frame(matrix(as.factor(rep(c(f[1], f[2]), times = 4)), nrow = 4))

.. 并重新运行上面的情节。也不能分配另一个级别,即使它是从最初的 2 个级别中选择的:

mon[1,1] <- f[1]

我对@9​​87654327@、relevel、order 等进行了很多尝试,但均未成功。有人有想法吗?

【问题讨论】:

    标签: r ggplot2 r-factor


    【解决方案1】:

    矩阵不能包含因子。当您将factor 放入matrix 时,它会被强制转换为character,并且未使用的级别会丢失。 as.data.frame(matrix(...))) 是一个坏习惯,因为这个(和其他类转换)的原因。

    这是一种在不丢失因子级别的情况下尽可能复制数据转换的方法:

    f <- factor(c("Free", "Work"))
    x= rep(f[2], 4)
    mon <- data.frame(A = x, B = x)
    str(mon)
    # 'data.frame': 4 obs. of  2 variables:
    #  $ A: Factor w/ 2 levels "Free","Work": 2 2 2 2
    #  $ B: Factor w/ 2 levels "Free","Work": 2 2 2 2
    ## looks good
    
    # What is y? What's the point?
    #mt    <- t(as.matrix(rev(data.frame(as.matrix(mon))))) #  change order of y
    
    mon$id = 1:nrow(mon)
    m     <- reshape2::melt(mon, id.vars = "id", factorsAsStrings = FALSE)
    
    levels(m$value)
    # [1] "Free" "Work"
    ## looks good
    

    现在,当我们开始绘图时,在比例中指定 drop = FALSE 以在图例中包含未使用的级别。 (如果您不想显示未使用的关卡,请使用默认的drop = TRUE。)由于关卡已经存在,我们不需要自定义labels。

    col   <- c("azure",  "orange")
    
    ggplot(m, aes(x = id, y = variable, fill = value)) +
      geom_tile(colour="grey10") +
      scale_fill_manual(values = col, name = NULL, drop = FALSE) +
      theme(panel.background = element_rect(fill = "white"), axis.ticks = element_blank()) +
      theme(axis.title.x = element_blank(), axis.title.y = element_blank()) 
    

    如果您想更加安全地使用色标,可以在将names 放入色标之前将其添加到values 向量中:

    names(col) = levels(f)
    

    另一种获取数据的方法是不用担心转换过程中的级别,并在最后使用适当的级别进行重构:

    # your original code:
    f             <- factor(c("Free", "Work"))
    mon           <- as.data.frame(matrix(as.factor(rep(f[2], times = 8)), nrow = 4)) 
    colnames(mon) <- c("A", "B")
    
    mt    <- t(as.matrix(rev(data.frame(as.matrix(mon))))) #  change order of y
    m     <- melt(mt)
    
    # add this at the end
    m$value = factor(m$value, levels = levels(f))
    
    # check that it looks good:
    str(m$value)
    # Factor w/ 2 levels "Free","Work": 2 2 2 2 2 2 2 2
    

    【讨论】:

      猜你喜欢
      • 2016-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-20
      • 2014-07-08
      相关资源
      最近更新 更多