【问题标题】:Create frequency tables for multiple factor columns in R为 R 中的多个因子列创建频率表
【发布时间】:2014-10-10 03:54:56
【问题描述】:

我是 R 的新手。我正在为我的工作编写一份关于常用函数/特性的语法的单独手册。我的示例数据框如下:

x.sample <-
structure(list(Q9_A = structure(c(5L, 3L, 5L, 3L, 5L, 3L, 1L, 
5L, 5L, 5L), .Label = c("Impt", "Neutral", "Not Impt at all", 
"Somewhat Impt", "Very Impt"), class = "factor"), Q9_B = structure(c(5L, 
5L, 5L, 3L, 5L, 5L, 3L, 5L, 3L, 3L), .Label = c("Impt", "Neutral", 
"Not Impt at all", "Somewhat Impt", "Very Impt"), class = "factor"), 
Q9_C = structure(c(3L, 5L, 5L, 3L, 5L, 5L, 3L, 5L, 5L, 3L
), .Label = c("Impt", "Neutral", "Not Impt at all", "Somewhat Impt", 
"Very Impt"), class = "factor")), .Names = c("Q9_A", "Q9_B", 
"Q9_C"), row.names = c(NA, 10L), class = "data.frame")

> x.sample
          Q9_A            Q9_B            Q9_C
1        Very Impt       Very Impt Not Impt at all
2  Not Impt at all       Very Impt       Very Impt
3        Very Impt       Very Impt       Very Impt
4  Not Impt at all Not Impt at all Not Impt at all
5        Very Impt       Very Impt       Very Impt
6  Not Impt at all       Very Impt       Very Impt
7             Impt Not Impt at all Not Impt at all
8        Very Impt       Very Impt       Very Impt
9        Very Impt Not Impt at all       Very Impt
10       Very Impt Not Impt at all Not Impt at all

我的原始数据框有 21 列。

如果我想求均值(将其视为序数变量):

> sapply(x.sample,function(x) mean(as.numeric(x), na.rm=TRUE))
Q9_A Q9_B Q9_C 
 4.0  4.2  4.2

我想为我的数据框中的所有变量制作一个频率表。我搜索了互联网和许多论坛,发现最近的命令是使用 sapply。但是当我这样做的时候,它全是 0。

> sapply(x.sample,function(x) table(factor(x.sample, levels=c("Not Impt at all", "Somewhat Impt",            "Neutral", "Impt", "Very Impt"), ordered=TRUE)))
                Q9_A Q9_B Q9_C
Not Impt at all    0    0    0
Somewhat Impt      0    0    0
Neutral            0    0    0
Impt               0    0    0
Very Impt          0    0    0

问题 如何使用 sapply 根据上表为数据框中的所有列(即因子)制作频率图表?

PS 很抱歉,如果这看起来很琐碎,但我已经搜索了 2 天没有答案并尝试了所有可能的组合。可能是我搜索的不够仔细=(

非常感谢。

【问题讨论】:

  • 不会sapply(x.sample, table) 做吗?
  • @RichardScriven - 差不多。除了按照factor 排序重新排列输出之外,这一切都做了。
  • @Richard Scriven:我尝试了你的方法,但它返回了一个错误。 “无效的大小争论”。
  • @RaphaelLee - 它绝对有效。使用代码从您的问题中尝试您自己的x.sample

标签: r r-factor sapply


【解决方案1】:

你快到了。只需对您的功能进行一点小改动,您就可以实现这一目标。 function(x) ... 中的 x 需要传递给 table() 调用:

levs <- c("Not Impt at all", "Somewhat Impt", "Neutral", "Impt", "Very Impt")
sapply(x.sample, function(x) table(factor(x, levels=levs, ordered=TRUE)))

对代码稍加修改可能也会使其更易于阅读:

sapply(lapply(x.sample,factor,levels=levs,ordered=TRUE), table)

#                Q9_A Q9_B Q9_C
#Not Impt at all    3    4    4
#Somewhat Impt      0    0    0
#Neutral            0    0    0
#Impt               1    0    0
#Very Impt          6    6    6

【讨论】:

  • 我知道我不能说“谢谢”,但您为我节省了在互联网上无休止地搜索的大量精力。无论如何,替换所有关卡的一种懒惰方法是使用: levs
  • @RaphaelLee - 你绝对可以说“谢谢”。投票赞成好的答案并接受对你有用的答案也是很好的礼仪。另外,当您接受答案时,您还会获得声誉。
【解决方案2】:

来晚了,但这里有一个reshape2 可能的解决方案。使用recast 可能非常简单,但我们需要在这里处理空因子级别,因此我们需要在meltdcast 中指定factorsAsStrings = FALSEdcast,而recast 不能传递参数到melt(只到dcast),就这样

library(reshape2)
x.sample$indx <- 1 
dcast(melt(x.sample, "indx", factorsAsStrings = FALSE), value ~ variable, drop = FALSE)
#             value Q9_A Q9_B Q9_C
# 1            Impt    1    0    0
# 2         Neutral    0    0    0
# 3 Not Impt at all    3    4    4
# 4   Somewhat Impt    0    0    0
# 5       Very Impt    6    6    6

如果我们不关心空关卡,那么一个快速的解决方案就是

recast(x.sample, value ~ variable, id.var = "indx")
#             value Q9_A Q9_B Q9_C
# 1            Impt    1    0    0
# 2 Not Impt at all    3    4    4
# 3       Very Impt    6    6    6

或者,如果速度是一个问题,我们可以使用data.atble 来做同样的事情

library(data.table)
dcast(melt(setDT(x.sample), measure.vars = names(x.sample), value.factor = TRUE), 
           value ~ variable, drop = FALSE)
#              value Q9_A Q9_B Q9_C
# 1:            Impt    1    0    0
# 2:         Neutral    0    0    0
# 3: Not Impt at all    3    4    4
# 4:   Somewhat Impt    0    0    0
# 5:       Very Impt    6    6    6

【讨论】:

    【解决方案3】:

    为什么不只是:

    > sapply(x.sample, table)
                    Q9_A Q9_B Q9_C
    Impt               1    0    0
    Neutral            0    0    0
    Not Impt at all    3    4    4
    Somewhat Impt      0    0    0
    Very Impt          6    6    6
    

    我们称它为“tbl”;

    tbl[ order(match(rownames(tbl), c("Not Impt at all", "Somewhat Impt", 
                                      "Neutral", "Impt", "Very Impt")) )   , ]
                    Q9_A Q9_B Q9_C
    Not Impt at all    3    4    4
    Somewhat Impt      0    0    0
    Neutral            0    0    0
    Impt               1    0    0
    Very Impt          6    6    6
    

    【讨论】:

    • 这总是会返回一个矩阵。只有在每一列中级别的数量和名称都相同时,这才有效。
    • 确实如此。这是我的语法错误。非常感谢!
    • 我的意思是写它不会总是返回一个矩阵。
    • 当然这可行,但我认为 OP 也特别希望重新排序结果。我想是否应该通过改变 data.frame 本身来完成这一点还有待商榷。
    • 我明白你的意思。也许通过将行名与c("Not Impt at all", "Somewhat Impt", "Neutral", "Impt", "Very Impt") 匹配?我认为在提供级别时不需要“有序”属性。
    猜你喜欢
    • 2013-03-08
    • 2017-05-22
    • 1970-01-01
    • 2018-09-21
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多