【问题标题】:Discretizing score relative to mean相对于均值离散化分数
【发布时间】:2015-01-09 22:50:00
【问题描述】:

我有包含日期​​、邮政编码和分数的数据。 我想离散化数据,使得同一月份的所有行和同一邮政编码高于同一月份的平均值,邮政编码得到 1,所有其他的得到零。

示例(数据框称为 score_df):

date       zip      score
2014-01-02 12345    10
2014-01-03 12345    20
2014-01-04 12345    2
2014-01-05 99885    15
2014-01-06 99885    12

输出:

date       zip      score    above_avg
2014-01-02 12345    10       0
2014-01-03 12345    20       1
2014-01-04 12345    3        0
2014-01-05 99885    15       1
2014-01-06 99885    12       0

到目前为止,我一直在使用低效的解决方案:

1.遍历所有月份并使用 ifelse 语句应用二进制条件

score_df$above_avg <- rep(0,length(score_df$score))
for (month in (1:12)) {
score_df$above_avg <- ifelse(as.numeric(substring(score_df$date,6,7)) == month,ifelse(score_df$score>quantile(score_df$score[as.numeric(substring(score_df$date,6,7)) == month],(0.5)),1,0),score_df$above_avg)
}

2.我也尝试使用聚合生成平均表,然后将平均列连接到原始数据框,然后应用二进制条件

avg_by_month_zip <- aggregate(score~month+zip,data=score_df,FUN=mean)
score_df$mean <- sqldf("select * from score_df join avg_by_month_zip on avg_by_month_zip.zip = score_df.zip and avg_by_month_zip.month = score_df.month")
score_df$discrete <- ifelse(score_df$score>score_df$mean,1,0)

我想在功能上做到这一点。 我知道如何在一个条件下(只是日期或只是 zip)在功能上做到这一点,但不是两个。我可以连接这两个字段以创建一个唯一字段。这将是一个快速解决方案,但我想知道是否有一种方法可以使用 apply 函数或 plyr 简单有效地完成此操作。

【问题讨论】:

    标签: r functional-programming aggregate plyr discretization


    【解决方案1】:

    假设您的日期值已正确编码(例如)

    score_df <- structure(list(date = structure(c(16072, 16073, 16074, 16075, 
    16076), class = "Date"), zip = c(12345L, 12345L, 12345L, 99885L, 
    99885L), score = c(10L, 20L, 2L, 15L, 12L)), .Names = c("date", 
    "zip", "score"), row.names = c(NA, -5L), class = "data.frame")
    

    那你就可以了

    with(score_df, ave(score, strftime(date, "%m"), zip, 
        FUN=function(x) ifelse(x>mean(x), 1, 0)))
    # [1] 0 1 0 1 0
    

    我们使用ave() 来计算所有月份/zip 组合的值(我们使用strftime() 从日期中获取月份)。

    【讨论】:

      【解决方案2】:

      我没有假设您有日期类变量(它们实际上是因素。)但基本上与应检查的 MrFlick 沿着相同的路线进行:

      > inp$above_avg <- with(inp, ave(score, zip, format(as.Date(date), "%m"), FUN=function(s) as.numeric(s > mean(s)) ) )
      > inp
              date   zip score above_avg
      1 2014-01-02 12345    10         0
      2 2014-01-03 12345    20         1
      3 2014-01-04 12345     2         0
      4 2014-01-05 99885    15         1
      5 2014-01-06 99885    12         0
      

      【讨论】:

        【解决方案3】:

        用 data.table 试试:

        library(data.table)
        ddt = data.table(score_df)
        ddt[,above_avg:=ifelse(score>round(mean(score),0),1,0),]
        ddt
                 date   zip score above_avg
        1: 2014-01-02 12345    10         0
        2: 2014-01-03 12345    20         1
        3: 2014-01-04 12345     2         0
        4: 2014-01-05 99885    15         1
        5: 2014-01-06 99885    12         0
        

        【讨论】:

          猜你喜欢
          • 2014-11-12
          • 1970-01-01
          • 2016-11-27
          • 1970-01-01
          • 1970-01-01
          • 2011-08-07
          • 1970-01-01
          • 1970-01-01
          • 2017-11-10
          相关资源
          最近更新 更多