9

我正在尝试获取特定列的行数。我有三列名称、年龄和专业。例如,我如何从这个列表中找出有多少 BIO 专业。

我有一个 DF <- (NAME, YEAR, MAJOR, GPA) 我想要一个函数,这样我就可以淘汰任何少于 20 人的专业。

所以我想要这样的东西,但在实际的 r 代码中。

DF <- function(x){
##  Y <- get number of people for each major
##  GPA [DF$Y < 20] <- NA

任何帮助,将不胜感激

4

3 回答 3

11

我认为目前提供的两种方法过于复杂。尝试其中任何一个,其中第二个显然是“正确的方法”。:-)(借用@gung的例子。)

#  1
> tapply( DF$MAJOR, DF$MAJOR, length)
 BIO ECON HIST  LIT MATH 
 181  155  297  303   64 

#  2
> table(DF$MAJOR)

 BIO ECON HIST  LIT

 MATH 
     181  155  297  303   64 

And as far as efficiency?

> system.time( {dt = data.table(DF)
+  foo <- dt[,.N,by=MAJOR] })
   user  system elapsed 
  1.384   0.027   1.417 
> system.time(foo<- table(DF$MAJOR) )
   user  system elapsed 
  0.110   0.025   0.134 
#edit:
> system.time( {dt = as.data.table(DF)
+  foo <- dt[,.N,by=MAJOR] })
   user  system elapsed 
  0.064   0.022   0.086 

回答如何将表格结果与每个学生记录相关联的评论中的附加问题,查看ave函数并使用带有“[”-extraction 或 with 的第一种方法subset

 DF$group.size <- ave(DF$MAJOR, DF$MAJOR, length)
 newDF <- DF[ DF$group.size >=20000 , ]
于 2013-06-24T01:12:39.947 回答
3

计算你有多少东西的基本方法是总结一个逻辑向量,如果原始元素是你想要计算的东西,逻辑向量的每个元素都是 1,否则为 0。

让我们从一些数据开始:

N = 1000
set.seed(2)
DF <- data.frame(NAME=as.character(1:N), 
                 YEAR=sample(c("Freshman","Sophomore","Junior","Senior"),
                             size=N, replace=T), 
                 MAJOR=sample(c("BIO","ECON","HIST","LIT","MATH"),size=N, 
                              replace=T, prob=c(.20, .15, .30, .30, .05)), 
                 GPA=runif(N, min=0, max=4))

因此,我们通过以下方式了解您拥有多少BIO个专业:

sum(DF$MAJOR=="BIO")
[1] 181

如果您想知道每个存在的专业有多少,您可以使用?unique获取专业列表,然后使用?lapply将上述函数应用于列表:

lapply(unique(DF$MAJOR), function(x){ sum(DF$MAJOR==x) })

这是一个稍微漂亮的版本:

cbind(levels(unique(DF$MAJOR)), 
      lapply(unique(DF$MAJOR), function(x){ sum(DF$MAJOR==x) }))
     [,1]   [,2]
[1,] "BIO"  297 
[2,] "ECON" 303 
[3,] "HIST" 181 
[4,] "LIT"  155 
[5,] "MATH" 64  

你应该可以从这里拿走它。


更新: @DWin 是对的,我把它弄得太复杂了。由于DF$MAJOR是一个因素,您可以简单地执行以下操作:

> summary(DF$MAJOR)
 BIO ECON HIST  LIT MATH 
 181  155  297  303   64 
于 2013-06-18T20:21:30.363 回答
2

再次,它是 data.table 包分组功能来拯救。有一个“.N”表示法,表示每组中的行数,它可以准确地为您提供所需的内容。借用上一个答案:

> N = 1000
> set.seed(2)
> dt <- data.table(NAME=as.character(1:N), 
+                  YEAR=sample(c("Freshman","Sophomore","Junior","Senior"),
+                              size=N, replace=T), 
+                  MAJOR=sample(c("BIO","ECON","HIST","LIT","MATH"),size=N, 
+                               replace=T, prob=c(.20, .15, .30, .30, .05)), 
+                  GPA=runif(N, min=0, max=4))
> dt[,.N,by=MAJOR]
   MAJOR   N
1:  HIST 297
2:   LIT 303
3:   BIO 181
4:  ECON 155
5:  MATH  64

所以现在是单线。它也很快(使用 N=1000000):

> system.time( foo <- cbind(levels(unique(DF$MAJOR)), 
+       lapply(unique(DF$MAJOR), function(x){ sum(DF$MAJOR==x) })) )
     user    system   elapsed 
    0.616     0.050     0.665 
> dt = data.table(DF)
> system.time( foo <- dt[,.N,by=MAJOR] )
     user    system   elapsed 
    0.039     0.002     0.042 
于 2013-06-19T22:09:50.830 回答