【问题标题】:How do you summarize columns based on unique IDs without knowing IDs in R?在不知道 R 中的 ID 的情况下,如何根据唯一 ID 汇总列?
【发布时间】:2014-10-10 07:41:56
【问题描述】:

我一直在浏览有关汇总数据的帖子,但似乎没有找到我想要的东西。

我希望创建一个汇总“计数表”,让我可以查看给患者服用某种药物的频率。一些患者同时接受多种药物的事实并不重要,因为我只想要一个所有药物的摘要,然后计算每个药物类别占所有药物的百分比。问题是,我不知道可能给予的药物的名称,它们被“隐藏”在data.frame 的某个地方,因此,我必须指定 R 必须首先查看哪些列才能创建一个“ list”,然后它可以通过它来汇总列。

我预计这指向plyr 包,但我尝试正确使用其中的功能直到现在还没有奏效。

我的df 看起来像这样

x <- sample(letters[1:4], 20, replace = TRUE)
y <- sample(letters[1:5], 20, replace = TRUE)
z <- sample(letters[1:6], 20, replace = TRUE)
df<-data.frame(x,y,z)
head(df)
  x y z
1 a a f
2 a c d
3 b b e
4 c d b
5 a a b
6 c d d

如您所见,data.frame 包含三列,它们有相同但也有不同的字母,表示所用药物的名称。

我现在想做的是创建一个独特字符列表,

unique(x)
unique(y)
unique(z)

作为我的参考列表,R 可以通过它总结每列中的计数。

summary(df)

返回每列计数的摘要,但不返回每个 ID 本身的摘要,也没有所有唯一计数的百分比。

我还尝试了以下方法,方向正确,但理想情况下,我希望有一个独特字符列表,我可以将其提供给 length 参数

ddply(df, .(x), summarize, counts=length(unique(y)))

知道我该怎么做吗?非常感谢帮助。

【问题讨论】:

  • sapply(df , function(x) 名称(table(x)) )
  • @BondedDust 我会使用lapply 而不是sapply。如果每个names(table(x)) 碰巧返回一个相同长度的向量,则输出将是一个数组而不是一个列表,如果您需要随后处理该对象,这可能会导致问题。
  • 对。甚至可以使用lapply(df, function(x) list( nams=unique(x), count=length(unique(x)))
  • 谢谢大家,但我认为这不是我问题的解决方案。这将返回每列每个字符的级别数,但不会给我整个 df 中的总和计数。例如,字母 a 在 df 中出现了 16 次......这就是我想要的输出。键入summary(df),您将看到每列每个字符的汇总计数,但我想要整个df,然后还返回每个字符的总计数百分比。这就是为什么我认为ddply 功能可能比lapply() 更合适...感谢您的时间和帮助!
  • 我想我找到了解决方案,我很好奇您对我的回答有何看法

标签: r count plyr dplyr summary


【解决方案1】:

如果您只想计算整个数据帧的数量,可以使用table(unlist(df))(另请参阅@goctlr 的答案)& 如果您还想获得概率:prop.table(table(unlist(df)))。如果您还想获取各个列的计数,则变得更加困难。

为了获取每列的计数和总计数,我编写了以下函数:

# some reproducible data:
set.seed(1)
x <- sample(letters[1:4], 20, replace = TRUE)
y <- sample(letters[1:5], 20, replace = TRUE)
z <- sample(letters[1:6], 20, replace = TRUE)
df <- data.frame(x,y,z)

# the function
func <- function(x) {
  x2 <- data.frame()
  nms <- names(x)
  id <- sort(unique(unlist(x)))
  for(i in 1:length(id)) {
    for(j in 1:length(nms)) {
      x2[i,j] <- sum(x[,j] %in% id[i])
    }
  }
  names(x2) <- nms
  x2$total <- rowSums(x2)
  x2 <- cbind(id,x2)
  assign("dat", x2, envir = .GlobalEnv)
}

使用func(df) 执行函数将在您的全局环境中为您提供一个数据框dat

> dat
  id x y z total
1  a 4 4 3    11
2  b 5 5 2    12
3  c 5 4 4    13
4  d 6 4 5    15
5  e 0 3 5     8
6  f 0 0 1     1

之后,您可以使用例如dplyr 包计算百分比:

library(dplyr)
dat <- dat %>% mutate(xperc=round(100*x/sum(total),1),
                      yperc=round(100*y/sum(total),1),
                      zperc=round(100*z/sum(total),1),
                      perc=round(100*total/sum(total),1))

导致:

> dat
  id x y z total xperc yperc zperc perc
1  a 4 4 3    11   6.7   6.7   5.0 18.3
2  b 5 5 2    12   8.3   8.3   3.3 20.0
3  c 5 4 4    13   8.3   6.7   6.7 21.7
4  d 6 4 5    15  10.0   6.7   8.3 25.0
5  e 0 3 5     8   0.0   5.0   8.3 13.3
6  f 0 0 1     1   0.0   0.0   1.7  1.7

【讨论】:

  • Jaap,这是一个很棒的功能!实际上,我会经常使用它,因为它是快速总结因素以了解 df 中发生的情况的好方法!但是,我有一个小问题。在应用您回复的第二部分时,我收到错误消息Error: could not find function "%&gt;%"。任何想法为什么?此外,无论如何,实际上可以在dat df 中附加一列,然后显示总数的百分比?或者我应该将变异的dat 保存为dat2 然后data.frame(dat, dat2)?感谢您的精彩回答!
  • 啊,我傻了。我输入了library(plyr) 而不是dplyr!我的错。对不起!!!我还有一个小问题,因为也许我不清楚。理想情况下,我希望变量atotal 列总和的百分比。我将变异重写为dat2 &lt;- dat %&gt;% mutate(Percentage=100*total/sum(total)- 对吗?看起来不错...感谢您的时间和帮助!
  • @OFish 没错。 (顺便说一句:您在最后一条评论中的代码末尾忘记了)
  • 我不得不说@Jaap - 这是一个非常方便的小代码,我想我会尝试进一步扩展它,这样我就可以构建data.tables like dat 并在行中执行诸如chisq.tests 之类的操作,并将p-values 作为附加列。并不是说它是分析数据的最佳方式,但它只是为论文等制作表格的一种快速方式……我对此非常非常兴奋。再次感谢您。
【解决方案2】:

对于整个数据框的计数摘要,您可以取消列出数据框,然后调用表函数:

table(unlist(df))

要获得总计数的百分比,保存结果并使用 prop.table 函数:

tout <- table(unlist(df))
prop.table(tout)

【讨论】:

  • 感谢@goctlr,这是一个方便的小功能。就个人而言,我发现 Jaap 的答案提供了一种格式,这是最好的,但拥有 prop.table 函数是一件好事。感谢您的时间和帮助!
  • 不错且简单的答案。然而,我对这个问题的理解是,@OFish 还想要各个列的计数。这就是为什么我没有给出这个答案。我现在还在我的答案中包含了tableprop.table 函数,以使其更加完整。
猜你喜欢
  • 1970-01-01
  • 2021-04-29
  • 2019-07-05
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多