使用reshape + cast聚合多个列

时间:2010-05-06 14:05:55

标签: r reshape

在R中,我有一个数据框,其中包含Seat(factor),Party(factor)和Votes(numeric)列。我想创建一个摘要数据框,其中包含Seat,Winning party和Vote share的列。例如,从数据框

df <- data.frame(party=rep(c('Lab','C','LD'),times=4),
                 votes=c(1,12,2,11,3,10,4,9,5,8,6,15),
                 seat=rep(c('A','B','C','D'),each=3))

我想获得输出

  seat winner voteshare
1    A      C 0.8000000
2    B    Lab 0.4583333
3    C      C 0.5000000
4    D     LD 0.5172414

我可以弄清楚如何实现这一目标。但我确信必须有一个更好的方法,可能是使用Hadley Wickham的reshape包裹的狡猾的单线。有什么建议吗?

对于它的价值,我的解决方案使用了我的包中的一个功能 djwutils_2.10.zip并按如下方式调用。但是有各种特殊情况它没有处理,所以我宁愿依赖别人的代码。

aggregateList(df, by=list(seat=seat),
              FUN=list(winner=function(x) x$party[which.max(x$votes)],
                       voteshare=function(x) max(x$votes)/sum(x$votes)))

3 个答案:

答案 0 :(得分:11)

Hadley的plyr包可以帮助你:

ddply(df, .(seat), function(x) data.frame(winner=x[which.max(x$votes),]$party, voteshare=max(x$votes)/sum(x$votes)))

答案 1 :(得分:3)

你可能是对的,有一个狡猾的单行。我倾向于赞成可理解的方法比聪明方法更好,尤其是当你第一次看到某些东西时。这是更冗长的替代方案。

votes_by_seat_and_party <- as.matrix(cast(df, seat ~ party, value="votes"))

   C Lab LD
A 12   1  2
B  3  11 10
C  9   4  5
D  6   8 15

seats <- rownames(votes_by_seat_and_party)
parties <- colnames(votes_by_seat_and_party)

winner_col <- apply(votes_by_seat_and_party, 1, which.max)
winners <- parties[winner_col]
voteshare_of_winner_by_seat <- apply(votes_by_seat_and_party, 1, function(x) max(x) / sum(x))

results <- data.frame(seat = seats, winner = winners, voteshare = voteshare_of_winner_by_seat)

  seat winner voteshare
1    A      C 0.8000000
2    B    Lab 0.4583333
3    C      C 0.5000000
4    D     LD 0.5172414

# Full voteshare matrix, if you're interested
total_votes_by_seat <- rowSums(votes_by_seat_and_party)
voteshare_by_seat_and_party <- votes_by_seat_and_party / total_votes_by_seat

答案 2 :(得分:2)

好的,所以3个解决方案......这是使用原始R的另一个更紧凑的解决方案。它是4个稀疏代码行。我假设缺失值为0,或者只是缺失,因为它无关紧要。我的猜测是,这将是您获取大量数据的最快代码。

#get a sum for dividing
s <- aggregate(df$votes, list(seat = df$seat), sum)
#extract the winner and seat
temp <- aggregate(df$votes, list(seat = df$seat), max)
res <- df[df$seat %in% temp$seat & df$votes %in% temp$x,]
res$votes <- res$votes / s$x

如果您愿意,请重命名列...

res $ names&lt; - c('party','voteshare','winner')

(如果出现平局,这将返回错误...您将能够在临时数据框中看到它)