R - 来自采样的频率直方图:效率等等

问题描述 投票:0回答:2

我是一名大学生,开始探索R参加考试。对于模糊的标题感到抱歉,因为我有很多与此帖相关的问题。

我遇到了对男性(M)或女性(F)人群进行抽样的问题。我希望定义一个函数,可以获取该群体中男性和女性的数量,然后创建大小为sample.numbersample.size样本,并返回一个数据框,其中包含样本总体大小的样本比例,以及相关频率。

我很肯定有一种简单且经过优化的方法可以做到这一点,但我写了一个小功能(几乎没有):

senators <- function(Fem = 13, 
                 Mal = 87, 
                 sample.size = 10, 
                 sample.number = 100){

pop <- c(rep("F", Fem), rep("M", Mal)) # I create the population base

popsa <- list(NA)           # I make some empty variables used later
popsa.factor <- list(NA)    # Not sure if this passage is even needed...
popsa.proportion <- list(NA)

这是一个for循环。我已经读过for循环是非常低效的方法。有没有更好的办法?

for(i in 1:sample.number){
  popsa[[i]] <- sample(pop, sample.size, replace = TRUE)
  popsa.factor[[i]] <- table(factor(popsa[[i]], levels = c("M", "F")))
  popsa.proportion[[i]] <- popsa.factor[[i]][2]/sample.size
  }

我首先使用样本分配列表popsa的每个元素,然后使用popsa从每个样本创建一个表,并将其存储在popsa.factor中。然后我计算出女性在总数中的比例并将其存储在popsa.proportion中。这个for循环对我来说似乎非常混乱,并且处理大量样本的速度非常慢。有没有更好,更有效的方式来完成我在这里所做的事情?

popsa.unlisted <- unlist(popsa.proportion)
popsa.frequency <- table(popsa.unlisted)

popsa.frame <- data.frame(Level = as.numeric(names(popsa.frequency)), 
                          Freq =  as.numeric(popsa.frequency))
return(popsa.frame)
} # This closes the function call

然后我取消列出popsa.proportion以获取向量中的每个比例,并将这些值表格化以获得频率,将它们存储到popsa.frequency中。现在我尝试将因子popsa.frequency转换为数据框,通过欺骗和转换popsa.frequency的名称作为数字并将它们存储为数据框的第一列。然后该函数返回popsa.frame,如我所愿。

然而,popsa.frame仍然在其第一列(popsa.frequency)中延续了Level的因子属性。我怎么能改变这个?我是不是该?

由于这些是样本分布的频率,我想从这个数据帧创建一个直方图,虽然hist()只接受数字向量,所以popsa.frame不是一个有效的对象。然而,plot(popsa.frame)或多或少地回报了我想要的东西。我怎样才能创建这样的直方图?

编辑:按照下面标记的答案,我还提出了如何简单地将函数创建的数据帧转换为hist()实际可用于创建频率直方图的对象(尽管使用条形图产生或多或少的相同图形,并且可能是一种更统计正确的方式来显示这样的结果):

result <- senators(Fem=13,Mal=87,sample.size=50,sample.number=10000)

raw <- sapply(1:length(result$Level), function(x){
  rep(result$Level, result$Freq)
})

hist(raw)
r performance histogram
2个回答
0
投票

列表和for循环的创建存在一些性能瓶颈。我能够使用sapply删除for loop和一些临时变量。

我仍然返回数据成名,另一个选项将返回向量答案,只是将结果传递给最终绘图的直方图绘制函数。

senators <- function(Fem = 13, 
                     Mal = 87, 
                     sample.size = 10, 
                     sample.number = 100){

  pop <- c(rep("F", Fem), rep("M", Mal)) # I create the population base

  answer<-sapply(1:sample.number, function(x){popsa <- sample(pop, sample.size, replace = TRUE);
                                            length(popsa[popsa=="F"])/sample.size})

popsa.frequency <- table(answer)

popsa.frame <- data.frame(Level = as.numeric(names(popsa.frequency)), 
                          Freq =  as.numeric(popsa.frequency))
return(popsa.frame)
} 

senators()   

0
投票

你的函数有一些默认值,只需要做data.frame就可以创建一个senators()

按照您的数据我会做:

df <- senators() # using default values
plot(df, type="h", lwd = 5, lend=1) # type changes your plot type while lwd changes line sizes, while lend would give squared aspect yo your bars.

看看?plot,看看你可以做的情节类型。此外,您可以通过执行?par查看更改参数的方式。

P.S。:看看这个post的线宽细节。

© www.soinside.com 2019 - 2024. All rights reserved.