Создание текущей счетной переменной в R?
У меня есть набор данных о результатах футбольного матча, и я надеюсь научиться R, создав ряд рейтингов, похожих на формулу World Football Elo. Я сталкиваюсь с проблемами с вещами, которые кажутся простыми в Excel, не совсем интуитивны в R. Например, первые 15 из 4270 наблюдений с необходимыми переменными:
date t.1 t.2 m.result
1 19960406 DC SJ 0.0
2 19960413 COL KC 0.0
3 19960413 NE TB 0.0
4 19960413 CLB DC 1.0
5 19960413 LAG NYRB 1.0
6 19960414 FCD SJ 0.5
7 19960418 FCD KC 1.0
8 19960420 NE NYRB 1.0
9 19960420 DC LAG 0.0
10 19960420 CLB TB 0.0
11 19960421 COL FCD 1.0
12 19960421 SJ KC 0.5
13 19960427 CLB NYRB 1.0
14 19960427 DC NE 0.5
15 19960428 FCD TB 1.0
Я хочу, чтобы иметь возможность создать новую переменную, которая будет работать счет t.1 и t.2 сыгранных матчей (т.е. экземпляры до указанной даты, что "DC" встречается в столбцах t. 1 или t.2):
date t.1 t.2 m.result ##t.1m ##t.2m
1 19960406 DC SJ 0.0 1 1
2 19960413 COL KC 0.0 1 1
3 19960413 NE TB 0.0 1 1
4 19960413 CLB DC 1.0 1 2
5 19960413 LAG NYRB 1.0 1 1
6 19960414 FCD SJ 0.5 1 2
7 19960418 FCD KC 1.0 2 2
8 19960420 NE NYRB 1.0 2 2
9 19960420 DC LAG 0.0 3 2
10 19960420 CLB TB 0.0 2 2
11 19960421 COL FCD 1.0 2 3
12 19960421 SJ KC 0.5 3 3
13 19960427 CLB NYRB 1.0 3 3
14 19960427 DC NE 0.5 4 3
15 19960428 FCD TB 1.0 4 3
в Excel это уравнение (относительно) simple = SUMPRODUCT, например:
E4=SUMPRODUCT((A:A<=A4)*(B:B=B4))+SUMPRODUCT((A:A<=A4)*(C:C=B4))
где E4 - t.1m для obs # 4, A: A - дата, B: B - t.1, C: C - t.2 и т.д.
Но в R я могу получить общий итоговый продукт, напечатанный для меня (т.е. "DC" сыграл 576 игр по моему набору данных), но по какой-то причине (возможно, что я новичок, нетерпелив, трепетал методом проб и ошибок) я "Я просто потерял, как сделать счетчик времени на данные наблюдений, и особенно, как сделать этот счетный счет переменной, что жизненно важно для любого индекса рейтинга игры. Я знаю, что" PlayerRatings" существует, я чувствую, что для своего R-образования я должен сделать это в пакете R без этого пакета. plyr или dplyr в порядке, конечно.
Для справки, вот мои данные для копирования или вставки в ваш R.
date<-c(19960406,19960413,19960413,19960413,19960413,19960414,19960418,19960420,19960420,19960420,19960421,19960421,19960427,19960427,19960428)
t.1<-c("DC","COL","NE","CLB","LAG","FCD","FCD","NE","DC","CLB","COL","SJ","CLB","DC","FCD")
t.2<-c("SJ","KC","TB","DC","NYRB","SJ","KC","NYRB","LAG","TB","FCD","KC","NYRB","NE","TB")
m.result<-c(0.0,0.0,0.0,1.0,1.0,0.5,1.0,1.0,0.0,0.0,1.0,0.5,1.0,0.5,1.0)
mtable<-data.frame(date,t.1,t.2,m.result)
mtable
Ответы
Ответ 1
Здесь очень простое решение, которое не очень красиво, но делает работу.
Сначала просто измените ваши данные, чтобы упростить сравнение:
mtable<-data.frame(date,t.1,t.2,m.result, stringsAsFactors = FALSE)
Отредактировано по:
Если вы хотите убедиться, что совпадения упорядочены по дате, вы можете использовать order
, как указано @eipi10:
mtable = mtable[order(mtable$date), ]
Отметим, что если даты указаны в формате, который не является целым порядком, вы можете сначала преобразовать их в формат даты с помощью as.Date()
.
Что мы будем делать, для каждой строки возьмем подмножество фрейма данных с столбцами t.1
и t.2
, со всеми строками от 1 до указанной строки. Итак, 1:1, 1: 2, 1: 3 и т.д. На каждом прогоне мы подсчитываем количество раз, когда команда появилась, и используйте это как результат для нового столбца.
mtable$t.1m <- sapply(1:nrow(mtable),
function(i) sum(mtable[1:i, c("t.1", "t.2")] == mtable$t.1[i]))
Это было сделано для команд в t.1
, с небольшим изменением аргумента после ==
мы можем сделать это для t.2
:
mtable$t.2m <- sapply(1:nrow(mtable),
function(i) sum(mtable[1:i, c("t.1", "t.2")] == mtable$t.2[i]))
Теперь наш dataframe выглядит так:
> mtable
date t.1 t.2 m.result t.1m t.2m
1 19960406 DC SJ 0.0 1 1
2 19960413 COL KC 0.0 1 1
3 19960413 NE TB 0.0 1 1
4 19960413 CLB DC 1.0 1 2
5 19960413 LAG NYRB 1.0 1 1
6 19960414 FCD SJ 0.5 1 2
7 19960418 FCD KC 1.0 2 2
8 19960420 NE NYRB 1.0 2 2
9 19960420 DC LAG 0.0 3 2
10 19960420 CLB TB 0.0 2 2
11 19960421 COL FCD 1.0 2 3
12 19960421 SJ KC 0.5 3 3
13 19960427 CLB NYRB 1.0 3 3
14 19960427 DC NE 0.5 4 3
15 19960428 FCD TB 1.0 4 3
Ответ 2
На шаге создания данных убедитесь, что stringsAsFactors = FALSE
избегает проблем. Тогда это легко сделать. (edit: Я сделал это всем примером dplyr
)
library(dplyr)
cross_count <- function(id, var) {
length(which(mtable[id, var] == mtable[1:id, ] %>% select(t.1, t.2) %>% unlist))
}
mtable %>%
arrange(date) %>% # This makes sure the dates are in order
mutate(id = 1:nrow(.)) %>%
rowwise() %>%
mutate(t.1m = cross_count(id, 2), t.2m = cross_count(id, 3))
date t.1 t.2 m.result id t.1m t.2m
1 19960406 DC SJ 0.0 1 1 1
2 19960413 COL KC 0.0 2 1 1
3 19960413 NE TB 0.0 3 1 1
4 19960413 CLB DC 1.0 4 1 2
5 19960413 LAG NYRB 1.0 5 1 1
6 19960414 FCD SJ 0.5 6 1 2
7 19960418 FCD KC 1.0 7 2 2
8 19960420 NE NYRB 1.0 8 2 2
9 19960420 DC LAG 0.0 9 3 2
10 19960420 CLB TB 0.0 10 2 2
11 19960421 COL FCD 1.0 11 2 3
12 19960421 SJ KC 0.5 12 3 3
13 19960427 CLB NYRB 1.0 13 3 3
14 19960427 DC NE 0.5 14 4 3
15 19960428 FCD TB 1.0 15 4 3
Ответ 3
Кажется, что отдельные столбцы t.1m и t.2m предназначены для бухгалтерского учета, и вас действительно интересует количество игр? Я использовал with()
для работы со столбцами mtable без необходимости писать mtable каждый раз
mtable$games <- with(mtable, {
Если какая-то команда играет, она играет как команда 1, так и команда 2
played <- t.1 == "DC" | t.2 == "DC"
Сравнение векторизовано, сравнивая каждый элемент столбца t.1 с "DC" и т.д., и логическое сравнение также векторизовано так, что один |
.
Сложная часть данных состоит в том, что несколько команд играют за один день, а в день матча (видимо) только фокальная команда должна увеличиваться. Я воспользовался этим, выяснив, как заказать игры, чтобы фокусная команда всегда была последней в порядке в тот день, когда она играла.
o <- order(date, played)
затем вычислил суммарную сумму играемых игр
games <- cumsum(played[o])
и вернуть игры в исходный порядок
games[order(o)]
})
Здесь результат
> head(mtable, 11)
date t.1 t.2 m.result games
1 19960406 DC SJ 0.0 1
2 19960413 COL KC 0.0 1
3 19960413 NE TB 0.0 1
4 19960413 CLB DC 1.0 2
5 19960413 LAG NYRB 1.0 1
6 19960414 FCD SJ 0.5 2
7 19960418 FCD KC 1.0 2
8 19960420 NE NYRB 1.0 2
9 19960420 DC LAG 0.0 3
10 19960420 CLB TB 0.0 2
11 19960421 COL FCD 1.0 3
Здесь функция, которая реализует это, позволяя легко специфицировать координационную команду
gamesplayed <- function(date, t1, t2, focal="DC") {
played <- t1 == focal | t2 == focal
o <- order(date, played)
cumsum(played[o])[order(o)]
}
Ответ 4
Чтобы выполнить это, используя тот же способ, что и вы упомянули:
sum(mtable$t.1 == 'DC', mtable$t.2 == 'DC')