0

我有一个非常大的数据集(> 100 万行),其中需要计算同一天的所有百分位数(例如,所有 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)和所有列(A、B、C 和 D)的所有 1 月 1 日。然后对所有 1 月 2 日、1 月 3 日、...、12 月 30 日和 12 月 31 日执行此操作。这可以通过使用嵌套 if 语句在 Excel 中的小型数据集轻松完成;例如,={PERCENTILE(IF(月($B$2:$B$1000000)="Jan",IF(日($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
4

2 回答 2

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
于 2013-02-21T05:54:36.387 回答
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。

于 2013-02-21T07:56:08.847 回答