2017-12-06 4 views
0

私は前にこの質問をしてみましたが、あまり言い表せませんでした。これは私がまだ解決していない新しい試みです。条件に基づいて2つ前の行の合計を累積的に加算する列を作成するにはどうすればよいですか?

winners、losers、date、winner_points、およびloser_pointsのデータセットがあります。

各行について、勝者と敗者の2つの新しい列が必要です。これは、これまでに獲得したポイントの数(勝者と敗者の両方)を示します。

例データ:

私はそれがこれまでのようなループのために行うことです解決しましたどのように
winner_points_sum <- c(0, 0, 1, 3, 1, 3, 5, 3, 5) 
loser_points_sum <- c(0, 2, 2, 1, 4, 5, 4, 7, 4) 
test_data <- data.frame(winner, loser, date = as.Date(date), winner_points, loser_points, winner_points_sum, loser_points_sum) 

library(dplyr) 
test_data$winner_points_sum_loop <- 0 
test_data$loser_points_sum_loop <- 0 

for(i in row.names(test_data)) { 
    test_data[i,]$winner_points_sum_loop <- 
    (
    test_data %>% 
     dplyr::filter(winner == test_data[i,]$winner & date < test_data[i,]$date) %>% 
     dplyr::summarise(points = sum(winner_points, na.rm = TRUE)) 
    + 
    test_data %>% 
     dplyr::filter(loser == test_data[i,]$winner & date < test_data[i,]$date) %>% 
     dplyr::summarise(points = sum(loser_points, na.rm = TRUE)) 
    ) 
} 

test_data$winner_points_sum_loop <- unlist(test_data$winner_points_sum_loop) 

winner <- c(1,2,3,1,2,3,1,2,3) 
loser <- c(3,1,1,2,1,1,3,1,2) 
date <- c("2017-10-01","2017-10-02","2017-10-03","2017-10-04","2017-10-05","2017-10-06","2017-10-07","2017-10-08","2017-10-09") 
winner_points <- c(2,1,2,1,2,1,2,1,2) 
loser_points <- c(1,0,1,0,1,0,1,0,1) 
test_data <- data.frame(winner, loser, date = as.Date(date), winner_points, loser_points) 

私は出力になりたいです

どのようにこの問題に取り組むべきですか?行番号が足りるとクエリにかなりの時間がかかります。私はAVE関数で詳しく説明しましたが、1つの列でプレイヤーポイントを勝者として合計することはできますが、ポイントを敗者として追加する方法を理解することはできません。

This is the end result (except last column)

+0

私は 'winner_points_sum'がどうあるべきかを理解していません。それはそれの上の行からすべての 'winner_points'の合計ですか?それを明確にすることはできますか? –

+0

私は全く混乱しています。 '勝者と敗者のポイントはどういう意味ですか?なぜ勝者1と敗者3ですか?どのようにして 'winner_points'と' loser_points'になったのですか?そしてループは何をしますか?これをいくつか明確にしてください。 –

+0

winner_points_sumは、勝者と敗者の両方の前回の試合での勝者ポイントの合計とみなされます。 勝者と敗者はポイントであるIDと同じです。 @MattW @Dピント –

答えて

2
winner <- c(1,2,3,1,2,3,1,2,3) 
loser <- c(3,1,1,2,1,1,3,1,2) 
date <- c("2017-10-01","2017-10-02","2017-10-03","2017-10-04","2017-10-05","2017-10-06","2017-10-07","2017-10-08","2017-10-09") 
winner_points <- c(2,1,2,1,2,1,2,1,2) 
loser_points <- c(1,0,1,0,1,0,1,0,1) 
test_data <- data.frame(winner, loser, date = as.Date(date), winner_points, loser_points) 


library(dplyr) 
library(tidyr) 

test_data %>% 
    unite(winner, winner, winner_points) %>%     # unite winner columns 
    unite(loser, loser, loser_points) %>%      # unite loser columns 
    gather(type, pl_pts, winner, loser, -date) %>%    # reshape 
    separate(pl_pts, c("player","points"), convert = T) %>%  # separate columns 
    arrange(date) %>%           # order dates (in case it's not) 
    group_by(player) %>%          # for each player 
    mutate(sum_points = cumsum(points) - points) %>%   # get points up to that date 
    ungroup() %>%            # forget the grouping 
    unite(pl_pts_sumpts, player, points, sum_points) %>%  # unite columns 
    spread(type, pl_pts_sumpts) %>%        # reshape 
    separate(loser, c("loser", "loser_points", "loser_points_sum"), convert = T) %>%    # separate columns and give appropriate names 
    separate(winner, c("winner", "winner_points", "winner_points_sum"), convert = T) %>% 
    select(winner, loser, date, winner_points, loser_points, winner_points_sum, loser_points_sum) # select the order you prefer 


# # A tibble: 9 x 7 
# winner loser  date winner_points loser_points winner_points_sum loser_points_sum 
# * <int> <int>  <date>   <int>  <int>    <int>   <int> 
# 1  1  3 2017-10-01    2   1     0    0 
# 2  2  1 2017-10-02    1   0     0    2 
# 3  3  1 2017-10-03    2   1     1    2 
# 4  1  2 2017-10-04    1   0     3    1 
# 5  2  1 2017-10-05    2   1     1    4 
# 6  3  1 2017-10-06    1   0     3    5 
# 7  1  3 2017-10-07    2   1     5    4 
# 8  2  1 2017-10-08    1   0     3    7 
# 9  3  2 2017-10-09    2   1     5    4 
+0

うん、これは私が考えたことはありません、それを解決する方法です。ありがとう! –

1

私は最終的にあなたが欲しいものを理解します。そして、各プレイヤーの累積ポイントを各時点で取得してから、元のtest_dataデータフレームに参加させるアプローチを取った。

winner <- c(1,2,3,1,2,3,1,2,3) 
loser <- c(3,1,1,2,1,1,3,1,2) 
date <- c("2017-10-01","2017-10-02","2017-10-03","2017-10-04","2017-10-05","2017-10-06","2017-10-07","2017-10-08","2017-10-09") 
winner_points <- c(2,1,2,1,2,1,2,1,2) 
loser_points <- c(1,0,1,0,1,0,1,0,1) 
test_data <- data.frame(winner, loser, date = as.Date(date), winner_points, loser_points) 

library(dplyr) 
library(tidyr) 

cum_points <- test_data %>% 
    gather(end_game_status, player_id, winner, loser) %>% 
    gather(which_point, how_many_points, winner_points, loser_points) %>% 
    filter(
    (end_game_status == "winner" & which_point == "winner_points") | 
     (end_game_status == "loser" & which_point == "loser_points")) %>% 
    arrange(date = as.Date(date)) %>% 
    group_by(player_id) %>% 
    mutate(cumulative_points = cumsum(how_many_points)) %>% 
    mutate(cumulative_points_sofar = lag(cumulative_points, default = 0)) 
    select(player_id, date, cumulative_points) 

output <- test_data %>% 
    left_join(cum_points, by = c('date', 'winner' = 'player_id')) %>% 
    rename(winner_points_sum = cumulative_points_sofar) %>% 
    left_join(cum_points, by = c('date', 'loser' = 'player_id')) %>% 
    rename(loser_points_sum = cumulative_points_sofar) 
output 
0

previous question of the OPに差がOPは、現在実際の日付より前に、すなわち、各プレイヤーはこれまでを獲得したポイントの累積和を求めていることです。さらに、サンプルデータセットには、各行を一意に識別するdate列が含まれています。

したがって、ここでもmy previous approachをいくつかの変更を加えて使用することができます。以下の解決策は、データをワイドからロングの形式に変え、2つの値の変数を同時に再構成し、各プレイヤーIDの累積合計を計算し、最後に長い形式から広い形式に再作成します。 の得点のみを合計するには、の実際の日付より前に行が1つ遅れています。

winnerおよびloserの各列には、それぞれのプレーヤーIDが含まれています。

library(data.table) 
cols <- c("winner", "loser") 
setDT(test_data)[ 
    # reshape multiple value variables simultaneously from wide to long format 
    , melt(.SD, id.vars = "date", 
     measure.vars = list(cols, paste0(cols, "_points")), 
     value.name = c("id", "points"))][ 
      # rename variable column 
      , variable := forcats::lvls_revalue(variable, cols)][ 
      # order by date and cumulate the lagged points by id 
      order(date), points_sum := cumsum(shift(points, fill = 0)), by = id][ 
       # reshape multiple value variables simultaneously from long to wide format 
       , dcast(.SD, date ~ variable, value.var = c("id", "points", "points_sum"))] 
  date id_winner id_loser points_winner points_loser points_sum_winner points_sum_loser 
1: 2017-10-01   1  3    2   1     0    0 
2: 2017-10-02   2  1    1   0     0    2 
3: 2017-10-03   3  1    2   1     1    2 
4: 2017-10-04   1  2    1   0     3    1 
5: 2017-10-05   2  1    2   1     1    4 
6: 2017-10-06   3  1    1   0     3    5 
7: 2017-10-07   1  3    2   1     5    4 
8: 2017-10-08   2  1    1   0     3    7 
9: 2017-10-09   3  2    2   1     5    4 
関連する問題