我的理解是,问题是要求为每一行找到较早的行,该行的赢家是赢家还是输家。然后从这些行中取 wpointp 为赢家的行和 lpointp 为输家的行并平均所有这些数字。
1) sqldf 我们首先将 wpointp 和 lpointp 设为数值,然后使用指示的 on 条件将结果左连接到自身,并使用 avg 生成显示的平均值。
library(data.table)
library(sqldf)
data2 <- copy(data)
data2[, c("wpointp", "lpointp") := .(as.numeric(wpointp), as.numeric(lpointp))]
sqldf("select a.*,
avg((a.Winner = b.Winner)*b.wpointp + (a.Winner = b.Loser)*b.lpointp) 'wpoint.av',
from data2 a
left join data2 b
on b.Date < a.Date and ((a.Winner = b.Winner) or (a.Winner = b.Loser))
group by a.rowid")
给予:
Date Winner Loser wpointp lpointp wpoint.av
1 2018-01-01 A B 52 48 NA
2 2018-01-02 D C 58 42 NA
3 2018-01-03 B A 51 49 48.0
4 2018-01-04 A C 61 39 50.5
5 2018-01-05 C B 59 41 40.5
6 2018-01-06 A C 55 45 54.0
2) 这仅使用 data.table。虽然我从初始版本开始添加了一些加速,但它可能会很慢。
Mean <- function(i) {
w <- data2$Winner[i]
data2[1:.N < i & (Winner == w | Loser == w),
mean((Winner == w) * wpointp + (Loser == w) * lpointp)]
}
data2 <- copy(data)
data2[, c("wpointp", "lpointp") := .(as.numeric(wpointp), as.numeric(lpointp))]
data2[, wpoint.av := sapply(.I, Mean)]
data2
给予:
Date Winner Loser wpointp lpointp wpoint.av
1: 2018-01-01 A B 52 48 NaN
2: 2018-01-02 D C 58 42 NaN
3: 2018-01-03 B A 51 49 48.0
4: 2018-01-04 A C 61 39 50.5
5: 2018-01-05 C B 59 41 40.5
6: 2018-01-06 A C 55 45 54.0
3) dplyr/tidyr 将指示的列转换为数字,转换为长格式,使用 cummean 计算滚动平均值,提取获胜者行并将它们连接回原始数据。
library(data.table)
library(dplyr)
library(tidyr)
data %>%
mutate(wpointp = as.numeric(wpointp), lpointp = as.numeric(lpointp)) %>%
pivot_longer(Winner:Loser) %>%
group_by(value) %>%
mutate(pointp.av =
lag(cummean((name=="Winner") * wpointp + (name=="Loser") * lpointp))) %>%
ungroup %>%
filter(name == "Winner") %>%
select(Date, pointp.av) %>%
right_join(data, by = "Date") %>%
select(Date, Winner, Loser, wpointp, lpointp, pointp.av)
给予:
# A tibble: 6 x 6
Date Winner Loser wpointp lpointp pointp.av
<chr> <chr> <chr> <chr> <chr> <dbl>
1 2018-01-01 A B 52 48 NA
2 2018-01-02 D C 58 42 NA
3 2018-01-03 B A 51 49 48
4 2018-01-04 A C 61 39 50.5
5 2018-01-05 C B 59 41 40.5
6 2018-01-06 A C 55 45 54
4) 这仅使用基数 R。首先使用 reshape 转换为长格式并按日期顺序对其进行排序。他们定义了一个 cumMean 函数并由 Winner 应用。最后提取出获胜者行。
varying <- list(c("Winner", "Loser"), c("wpointp", "lpointp"))
long <- reshape(data, dir = "long", varying = varying)
long <- long[order(long$Date), ]
cumMean <- function(x) c(NA, head(cumsum(x), -1)) / (seq_along(x) - 1)
long2 <- transform(long, av = ave(as.numeric(wpointp), Winner, FUN = cumMean))
subset(long2, time == 1)
给予:
Date time Winner wpointp id av
1: 2018-01-01 1 A 52 1 NA
2: 2018-01-02 1 D 58 2 NA
3: 2018-01-03 1 B 51 3 48.0
4: 2018-01-04 1 A 61 4 50.5
5: 2018-01-05 1 C 59 5 40.5
6: 2018-01-06 1 A 55 6 54.0