【问题标题】:Counting elements by row with dplyr使用 dplyr 按行计算元素
【发布时间】:2018-07-24 00:17:08
【问题描述】:

我有一个数据集,其中的数据以一种不是特别有用的格式提供。这是一个较小的例子:

你有一副牌,发了十张牌,记录下这些牌,这个过程重复 5 次,存储在一个 5x10 的矩阵中。为简单起见,我们只将牌编号为 1-13 而不是 Ace,1,2...King;每张牌有四张,与他们的花色无关。

set.seed(7)
tmpdf=data.frame(matrix(0,nrow=5,ncol=10))

for(i in 1:nrow(tmpdf)) {
    tmpdf[i,]=sample(rep(c(1:13),each=4),size=10)
}
> tmpdf
  X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 13  6  2  1  3 10  4 11  2   5
2  3  3 10  2  6  1  7  1 11   4
3  9  4 13 12 12  1  8  6 11  13
4  9  4  3 13  5 10  6 13 10   5
5 11  5 10  6 11  4  1 10 10  13

每张牌的栏目并不重要,重要的是每张牌发给每手牌的数量。我知道如何在基础 R 中循环重组它,但不是整洁的方式。

newdf=data.frame(matrix(0,nrow=5,ncol=13))
names(newdf)=as.character(c(1:13))

for(i in 1:nrow(tmpdf)) {
    tmp=table(factor(as.numeric(tmpdf[i,])))
    newdf[i,names(tmp)]=tmp
}

> newdf
  1 2 3 4 5 6 7 8 9 10 11 12 13
1 1 2 1 1 1 1 0 0 0  1  1  0  1
2 2 1 2 1 0 1 1 0 0  1  1  0  0
3 1 0 0 1 0 1 0 1 1  0  1  2  2
4 0 0 1 1 2 1 0 0 1  2  0  0  2
5 1 0 0 1 1 1 0 0 0  3  2  0  1

我怀疑 count 和/或 summarise 会很有用,但到目前为止我无法开发解决方案,也无法在此处找到问题/答案。

【问题讨论】:

  • 你是说要使用tidy分析原则从tmpdf转到newdf?
  • 似乎 newdf 的格式不整洁,所以我很困惑为什么你会关心中间步骤是否使用 tidy 原则。
  • 我很惊讶新的数据框不被认为是整洁的——每一行都是一个观察(手),每一列是一个变量(那手有多少给定类型的牌?)。但是,是的,我正在尝试将 tmpdf 转换为整洁的格式,我们知道每手牌中有多少张给定的牌。如果 newdf 实际上不是整洁的格式,那么我更愿意知道如何使它真正整洁。
  • 我一直在想,我会将每张牌称为观察结果,而手牌是要分组的变量,所以我会说你需要两列,第 1 列是手牌编号(值 1 到 5),第 2 列是数字 1 到 13。然后将有 50 行,每张卡一个。我认为这类似于@CPak 在下面所做的。感谢您提出这个问题并促进讨论!

标签: r dplyr tidyr summarize


【解决方案1】:

一个简洁的方法是

library(qdapTools)
mtabulate(as.data.frame(t(tmpdf)))
#   1 2 3 4 5 6 7 8 9 10 11 12 13
#V1 1 2 1 1 1 1 0 0 0  1  1  0  1
#V2 2 1 2 1 0 1 1 0 0  1  1  0  0
#V3 1 0 0 1 0 1 0 1 1  0  1  2  2
#V4 0 0 1 1 2 1 0 0 1  2  0  0  2
#V5 1 0 0 1 1 1 0 0 0  3  2  0  1

或者在管道中使用mtabulate

tmpdf %>%
      t %>% 
      as_tibble %>%
      mtabulate

或base R

table(stack(as.list(as.data.frame(t(tmpdf))))[2:1])

【讨论】:

    【解决方案2】:

    一个整洁的方法是tidyr::gather你所有的价值观,dplyr::count他们,然后tidyr::spread他们

    tmpdf %>%
      group_by(rn = row_number()) %>%
      gather(key, value, X1:X10) %>%
      ungroup() %>%
      count(rn, value) %>%
      group_by(rn) %>%
      spread(value, n, fill=0)
    
      # A tibble: 5 x 14
             # rn   `1`   `2`   `3`   `4`   `5`   `6`   `7`   `8`   `9`  `10`  `11`  `12`  `13`
        # * <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
        # 1     1  1.00  2.00  1.00  1.00  1.00  1.00  0     0     0     1.00  1.00  0     1.00
        # 2     2  2.00  1.00  2.00  1.00  0     1.00  1.00  0     0     1.00  1.00  0     0   
        # 3     3  1.00  0     0     1.00  0     1.00  0     1.00  1.00  0     1.00  2.00  2.00
        # 4     4  0     0     1.00  1.00  2.00  1.00  0     0     1.00  2.00  0     0     2.00
        # 5     5  1.00  0     0     1.00  1.00  1.00  0     0     0     3.00  2.00  0     1.00
    

    【讨论】:

    • 哇,这么多步骤!非常感谢!
    • 在@CPak 的代码中,按rn 分组似乎是不必要的。以下代码也适用:tmpdf %&gt;% mutate(rn=row_number()) %&gt;% gather(key, value, X1:X10) %&gt;% count(rn, value) %&gt;% spread(value, n, fill=0).
    【解决方案3】:

    不是tidy 的方式,但无论如何可能对你有用,因为它非常简短:

    data.frame(sapply(1:13,function(x) {rowSums(tmpdf==x)}))
    

    输出:

      X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13
    1  1  2  1  1  1  1  0  0  0   1   1   0   1
    2  2  1  2  1  0  1  1  0  0   1   1   0   0
    3  1  0  0  1  0  1  0  1  1   0   1   2   2
    4  0  0  1  1  2  1  0  0  1   2   0   0   2
    5  1  0  0  1  1  1  0  0  0   3   2   0   1
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2014-05-11
      • 2015-04-13
      • 1970-01-01
      • 2021-10-01
      • 2021-05-07
      • 1970-01-01
      • 2022-11-20
      • 2015-11-07
      相关资源
      最近更新 更多