1

在 R 中,我有一个数据框,其中包含 Seat(因子)、Party(因子)和 Votes(数字)列。我想创建一个包含席位、获胜方和投票份额列的摘要数据框。例如,从数据框

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)))
4

3 回答 3

11

Hadley 的 plyr 软件包可以帮助您:

ddply(df, .(seat), function(x) data.frame(winner=x[which.max(x$votes),]$party, voteshare=max(x$votes)/sum(x$votes)))
于 2010-05-06T14:52:45.547 回答
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
于 2010-05-06T15:36:42.080 回答
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 <- c('party', 'voteshare', 'winner')

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

于 2010-05-06T17:16:32.350 回答