У меня есть данные с датой, почтовым индексом и счетом. Я хотел бы дискретизировать данные так, чтобы все строки того же месяца и того же почтового индекса выше среднего для того же месяца и почтового индекса получили 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.Looping через все месяцы и применение бинарного состояния с оператором 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.I также попытались создать среднюю таблицу с помощью совокупности, то присоединение средней колонки к исходному кадру данных, а затем применяя бинарное условию
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.