查找大量不规则数据集的每日百分位数

时间:2013-02-21 05:31:18

标签: r percentile

我有一个非常大的数据集(> 1百万行),其中需要计算所有当天的百分位数(例如,所有1月1日,全部是1月2日,...,所有12月31日)。同一年,月和日有许多行,数据不同。以下是数据示例:

    Year  Month  Day  A  B  C  D
    2007  Jan    1    1  2  3  4
    2007  Jan    1    5  6  7  8
    2007  Feb    1    1  2  3  4
    2007  Feb    1    5  6  7  8
    .
    .
    2010  Dec    30   1  2  3  4
    2010  Dec    30   5  6  7  8
    2010  Dec    31   1  2  3  4
    2010  Dec    31   5  6  7  8

因此,要计算1月1日的第95百分位数,它需要包括所有年份(例如,2007-2010)的所有1月1日以及所有列(A,B,C和D)。然后在1月2日,1月3日,...,12月30日和12月31日完成。通过使用嵌套的if语句,可以使用Excel中的小数据集轻松完成此操作。例如,= {PERCENTILE(IF(月($ B $ 2:$ B $ 1000000)=“Jan”,IF(Day($ C $ 2:$ C $ 1000000)=“1”,$ D $ 2:$ G $ 1000000)), 95%)}

然后可以将百分位数添加到仅包含月份和日期的新数据表中:

    Month  Day  P95  P05
    Jan    1
    Jan    2
    Jan    3
    .
    .
    Dec    30
    Dec    31

然后使用百分位数,我需要评估列名A,B,C和D中各自日期(例如,1月1日)的每个数据值是否大于P95或小于P05。然后可以将新列添加到包含1或0的第一个数据表中(如果更大或更小则为1,如果不大于或小于百分位数则为0):

    Year  Month  Day  A  B  C  D  A05  B05  C05  D05  A95  B95  C95  D95
    2007  Jan    1    1  2  3  4  1    0    0    0    0    0    0    0
    2007  Jan    1    5  6  7  8  0    0    0    0    0    0    1    1
    .
    .
    2010  Dec    31   5  6  7  8  0    0    0    0    0    0    0    1

2 个答案:

答案 0 :(得分:1)

我已将您的数据称为dat

library(plyr)
library(reshape2)

# melt values so all values are in 1 column
dat_melt <- melt(dat, id.vars=c("Year", "Month", "Day"), variable.name="letter", value.name="value")

# get quantiles, split by day
dat_quantiles <- ddply(dat_melt, .(Month, Day), summarise, 
                   P05=quantile(value, 0.05), P95=quantile(value, 0.95))

# merge original data with quantiles
all_dat <- merge(dat_melt, dat_quantiles)

# See if in bounds
all_dat <- transform(all_dat, less05=ifelse(value < P05, 1, 0), greater95=ifelse(value > P95, 1, 0))


   Month Day Year letter value  P05  P95 less05 greater95
1    Dec  30 2010      A     1 1.35 7.65      1         0
2    Dec  30 2010      A     5 1.35 7.65      0         0
3    Dec  30 2010      B     2 1.35 7.65      0         0
4    Dec  30 2010      B     6 1.35 7.65      0         0
5    Dec  30 2010      C     3 1.35 7.65      0         0
6    Dec  30 2010      C     7 1.35 7.65      0         0
7    Dec  30 2010      D     4 1.35 7.65      0         0
8    Dec  30 2010      D     8 1.35 7.65      0         1
9    Dec  31 2010      A     1 1.35 7.65      1         0
10   Dec  31 2010      A     5 1.35 7.65      0         0
11   Dec  31 2010      B     2 1.35 7.65      0         0
12   Dec  31 2010      B     6 1.35 7.65      0         0
13   Dec  31 2010      C     3 1.35 7.65      0         0
14   Dec  31 2010      C     7 1.35 7.65      0         0
15   Dec  31 2010      D     4 1.35 7.65      0         0
16   Dec  31 2010      D     8 1.35 7.65      0         1
17   Feb   1 2007      A     1 1.35 7.65      1         0
18   Feb   1 2007      A     5 1.35 7.65      0         0
19   Feb   1 2007      B     2 1.35 7.65      0         0
20   Feb   1 2007      B     6 1.35 7.65      0         0
21   Feb   1 2007      C     3 1.35 7.65      0         0
22   Feb   1 2007      C     7 1.35 7.65      0         0
23   Feb   1 2007      D     4 1.35 7.65      0         0
24   Feb   1 2007      D     8 1.35 7.65      0         1
25   Jan   1 2007      A     1 1.35 7.65      1         0
26   Jan   1 2007      A     5 1.35 7.65      0         0
27   Jan   1 2007      B     2 1.35 7.65      0         0
28   Jan   1 2007      B     6 1.35 7.65      0         0
29   Jan   1 2007      C     3 1.35 7.65      0         0
30   Jan   1 2007      C     7 1.35 7.65      0         0
31   Jan   1 2007      D     4 1.35 7.65      0         0
32   Jan   1 2007      D     8 1.35 7.65      0         1

答案 1 :(得分:0)

这些行中的某些内容可以合并到原始数据框:

aggregate(dfrm[ , c("A","B","C","D")] , list(dfrm$month, dfrm$day), 
                                              FUN=quantile, probs=c(0.05,0.95))

注意我建议merge()。您的描述建议(但不明确)您希望所有年份的Jan-1值一起提交。我认为这比你在Excel中使用的表达“更容易”。这在所有四列上均为0.05和0.95。