R - 秩和组

R - Rank and Group

希望不大,但我还是会试试。我想根据可用的 data.frame 建立百分位数(100 组)或十分位数(10 组)。 在此示例中,我有一个包含 891 条记录的数据框。在这个 data.frame 中,我有以下变量。

我需要你的帮助来构建下面的等效 table。通过更改组数,我可以使用 xbeta 将其拆分为 10 或 100。顶行是总数(可通过 TYPE 识别),我想生成以下内容 table(有关详细信息,请参见下面的 table)

非常感谢您的帮助。 吉姆学习 R

r_xbeta _TYPE_  n   GOOD    BAD xbeta_min   xbeta_max   xbeta_mean  xbeta_MEDIAN    GB_ODDS LN_GB_ODDS  Cummu_Good  Cummu_Bad   Cummu_Good_pct  Cummu_Bad_pct
.       0       891 342     549 -4.42       3.63        -0.7        -1.09           0.62295 -0.47329    342         549         100%            100%
0       1       89  4       85  -4.42       -2.7        -3.6        -3.57           0.04706 -3.05636    4           85          1.20%           15%
1       1       89  12      77  -2.69       -2.37       -2.55       -2.54           0.15584 -1.8589     16          162         4.70%           30%
2       1       87  12      75  -2.35       -1.95       -2.16       -2.2            0.16    -1.83258    28          237         8.20%           43%
3       1       93  14      79  -1.95       -1.54       -1.75       -1.79           0.17722 -1.73039    42          316         12%             58%
4       1       88  10      78  -1.53       -1.09       -1.33       -1.33           0.12821 -2.05412    52          394         15%             72%
5       1       89  27      62  -1.03       -0.25       -0.67       -0.69           0.43548 -0.8313     79          456         23%             83%
6       1       89  44      45  -0.24       0.33        0.05        0.03            0.97778 -0.02247    123         501         36%             91%
7       1       89  54      35  0.37        1.07        0.66        0.63            1.54286 0.43364     177         536         52%             98%
8       1       88  77      11  1.08        2.15        1.56        1.5             7       1.94591     254         547         74%             100%
9       1       90  88      2   2.18        3.63        2.77        2.76            44      3.78419     342         549         100%            100%

A reproducible example 会很棒,也就是说,我们可以将其复制粘贴到我们的终端以演示您的问题。例如,这是我将使用的数据框:

set.seed(1) # so you get the same random numbers as me
my_dataframe <- data.frame(Unique_ID = 1:891,
                           xbeta=rnorm(891, sd=10),
                           Good=round(runif(891) < 0.5),
                           Bad=round(runif(891) < 0.5))
head(my_dataframe)
#   Unique_ID     xbeta Good Bad
# 1         1 -6.264538    1   0
# 2         2  1.836433    1   0
# 3         3 -8.356286    0   1
# 4         4 15.952808    1   1
# 5         5  3.295078    1   0
# 6         6 -8.204684    1   1

(具体数字对你的问题无关紧要,这就是我随机编造数字的原因)。

想法是:

  • 算出每行属于哪个分位数:参见?quantile。您可以指定您想要的分位数(我已经显示了十分位数)

    quantile(my_dataframe$xbeta, seq(0, 1, by=.1))
    #          0%         10%         20%         30%         40%         50%         60%         70%         80%         90%        100% 
    # -30.0804860 -13.3880074  -8.7326454  -5.1121923  -3.0097613  -0.4493361   2.3680366   5.3732613   8.7867326  13.2425863  38.1027668 
    

    这给出了分位数截止值;如果你在这些上使用 cut,你可以添加一个变量,说明每行在哪个分位数 (?cut):

    my_dataframe$quantile <- cut(my_dataframe$xbeta,
                                 quantile(my_dataframe$xbeta, seq(0, 1, by=.1)))
    

    看看 head(my_dataframe) 看看它做了什么。 quantile 列是一个因素。

  • 按分位数拆分您的数据框,并计算每个数据框的统计数据。您可以为此使用 plyrdplyrdata.table 包;我推荐前两个中的一个,因为你是 R 的新手。如果你需要高效地对巨大的表(数千行)进行大量合并和计算,请使用 data.table,但学习曲线要​​陡峭得多。我将向您展示 plyr 纯粹是因为这是我认为最简单的方法。 dplyr 非常相似,只是语法不同。

    # The idea: `ddply(my_dataframe, .(quantile), FUNCTION)` applies FUNCTION
    #  to each subset of `my_dataframe`, where we split it up into unique
    # `quantile`s.
    # For us, `FUNCTION` is `summarize`, which calculates summary stats
    #  on each subset of the dataframe.
    # The arguments after `summarize` are the new summary columns we
    #  wish to calculate.
    
    library(plyr)
    output = ddply(my_dataframe, .(quantile), summarize,
                   n=length(Unique_ID), GOOD=sum(Good), BAD=sum(Bad),
                   xbeta_min=min(xbeta), xbeta_max=max(xbeta),
                   GB_ODDS=GOOD/BAD) # you can calculate the rest yourself,
                                     # "the rest should be self explanatory".
    > head(output, 3)
           quantile  n GOOD BAD  xbeta_min  xbeta_max   GB_ODDS
     1 (-30.1,-13.4] 89   41  39 -29.397737 -13.388007 1.0512821
     2 (-13.4,-8.73] 89   49  45 -13.353714  -8.732645 1.0888889
     3 (-8.73,-5.11] 89   46  48  -8.667335  -5.112192 0.9583333
    
  • 计算其他列。请参阅(例如)?cumsum 了解累积总和。例如output$cummu_good <- cumsum(output$GOOD).
  • 添加 'total' 行。你应该能够做到这一点。您可以使用 rbind.
  • 添加额外的行到 output

这是我的脚本在数学咖啡指导下的最终版本。由于“'breaks' 不是唯一的”错误,我不得不使用 .bincode 而不是建议的剪切。

谢谢大家

set.seed(1) # so you get the same random numbers as me
my_dataframe <- data.frame(Unique_ID = 1:891,
                           xbeta=rnorm(891, sd=10),
                           Good=round(runif(891) < 0.5),
                           Bad=round(runif(891) < 0.5))
head(my_dataframe)
quantile(my_dataframe$xbeta, seq(0, 1, by=.1))
my_dataframe$quantile = .bincode(my_dataframe$xbeta,quantile(my_dataframe$xbeta,seq(0,1,by=.1)))
library(plyr)
output = ddply(my_dataframe, .(quantile), summarize,
               n=length(Unique_ID), GOOD=sum(Good), BAD=sum(Bad),
               xbeta_min=min(xbeta), xbeta_max=max(xbeta), xbeta_median=median(xbeta), xbeta_mean=mean(xbeta),
               GB_ODDS=GOOD/BAD, LN_GB_ODDS = log(GOOD/BAD))
output$cummu_good = cumsum(output$GOOD)
output$cummu_bad = cumsum(output$BAD)
output$cummu_n = cumsum(output$n)
output$sum_good = sum(output$GOOD)
output$sum_bad = sum(output$BAD)
output$cummu_good_pct = cumsum(output$GOOD/output$sum_good)
output$cummu_bad_pct = cumsum(output$BAD/output$sum_bad)
output[["sum_good"]]=NULL
output[["sum_bad"]]=NULL
output