2015-05-11 25 views
13

Mam zestaw danych wyników meczów piłki nożnej i mam nadzieję nauczyć się R, tworząc działający zestaw ocen podobnych do formuły World Football Elo. Używam kłopoty z rzeczy, które wydają się być prosty w programie Excel nie są dokładnie intuicyjny w R. Na przykład, pierwszy 15 z 4270 obserwacji z niezbędnych zmiennych:Tworzenie zmiennej zliczającej w R?

 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 

Chcę być w stanie stworzyć nową zmienną, która będzie liczoną liczbą pełnych dopasowań t.1 i t.2 (tzn. instancje do danej daty, w której występuje "DC" w kolumnach t.1 lub 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, to jest (stosunkowo) prosty = równanie SUMA.ILOCZYNÓW, np

E4=SUMPRODUCT((A:A<=A4)*(B:B=B4))+SUMPRODUCT((A:A<=A4)*(C:C=B4)) 

gdzie E4 jest t.1m dla obs # 4, A: jest data, B: B jest t.1, C: C jest t.2 itp

Ale w R, można uzyskać całkowity sumproduct wydrukowano dla mnie (np "DC" rozegrał 576 gier w moim zestawie danych), ale z jakiegoś powodu (prawdopodobnie, że jestem nowy, niecierpliwy, wstrząśnięty próbą i błędem) po prostu straciłem umiejętność liczenia danych obserwacyjnych, a zwłaszcza jak sprawić, aby to działanie było zliczane w zmiennej, która jest niezbędna dla każdego indeksu rankingu gier. Wiem, że istnieje "PlayerRatings", czuję, że dla mojego wykształcenia R powinienem móc to zrobić w pakiecie R bez tego pakietu. Oczywiście plyr lub dplyr są w porządku.

Dla porównania, tutaj jest moje dane, aby skopiować/wkleić do swojej 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 
+0

pokrewne [Uruchamianie Ilość podstawie polu R] (http://stackoverflow.com/q/31259932/452096) . Ta dała odpowiedzi, które przebiegały o wiele szybciej w moim dużym problemie niż zaakceptowana odpowiedź poniżej. –

Odpowiedz

4

Oto bardzo proste rozwiązanie, które nie jest ładny, ale spełnia swoje zadanie.

Pierwsze, po prostu zmiana danych, aby porównania łatwiejsze:

mtable<-data.frame(date,t.1,t.2,m.result, stringsAsFactors = FALSE) 

edytowane w:

Jeśli chcesz zapewnić mecze są sortowane według daty, można użyj order jak wskazano przez @ eipi10:

mtable = mtable[order(mtable$date), ] 

Należy zauważyć, że w przypadku, gdy daty są w formacie, w którym kolejność chronologiczna nie jest liczbą całkowitą, można je najpierw przekonwertować na format daty przy użyciu numeru as.Date().


Co mamy zamiar zrobić, to dla każdego wiersza, wziąć podzbiór dataframe z kolumnami t.1 i t.2 ze wszystkich wierszy od 1 do wspomnianego rzędu. Tak więc 1: 1, 1: 2, 1: 3 itd. Przy każdym uruchomieniu liczymy ile razy drużyna pojawiła się i użyjemy jej jako wyniku dla nowej kolumny.

mtable$t.1m <- sapply(1:nrow(mtable), 
      function(i) sum(mtable[1:i, c("t.1", "t.2")] == mtable$t.1[i])) 

Zrobiono to dla zespołów w t.1, z małą zmianą na argument po == możemy zrobić to za t.2:

mtable$t.2m <- sapply(1:nrow(mtable), 
      function(i) sum(mtable[1:i, c("t.1", "t.2")] == mtable$t.2[i])) 

Teraz nasz dataframe wygląda następująco:

> 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 
+0

Dziękujemy! To działa dobrze. Kontynuacja: Zauważyłem, że w ogóle nie odnosiłeś się do zmiennej daty. Załóżmy, że moje dane zostały rozproszone na zmiennych daty i chcę zamówić mój licznik w najwcześniejszym czasie, w którym drużyna gra. Czy kod się zmienia? –

+1

Możesz sortować tabelę według daty przed uruchomieniem kodu Molx: 'mtable = mtable [order (mtable $ date),]'. – eipi10

5

W kroku tworzenia danych upewnij się, że chcesz uniknąć problemów. Wtedy jest to łatwe. (Edit: Zrobiłem to all dplyr przykład)

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 
-1

Aby to osiągnąć stosując podobny sposób, jak pan wspomniał:

sum(mtable$t.1 == 'DC', mtable$t.2 == 'DC') 
+0

Wynik jest następujący: 4 –

0

Wygląda oddzielnych kolumnach t.1m i t.2m są do księgowości, a tak naprawdę interesuje Cię tylko liczba rozegranych gier? Kiedyś with() pracować z kolumnami mtable bez konieczności pisania mtable każdorazowo

mtable$games <- with(mtable, { 

Jeśli dana drużyna gra, to gra zarówno jako zespół 1 lub zespół 2

played <- t.1 == "DC" | t.2 == "DC" 

Porównanie jest wektorowy , porównując każdy element kolumny t.1 z "DC", itp., a logiczne porównanie jest również wektoryzowane, więc pojedynczy |.

Trudną częścią danych jest to, że kilka drużyn gra w jeden dzień, a w dniu meczu (podobno) tylko zespół ogniskowej powinien zostać zwiększony. I zakwaterowani to przez zastanawianie się, jak zamówić gry tak, że centralny zespół był zawsze ostatnia w kolejności z dniem grał

o <- order(date, played) 

następnie oblicza łączną sumę rozegranych

games <- cumsum(played[o]) 

i umieścić gry z powrotem do ich pierwotnego celu

games[order(o)] 
}) 

Oto wynik

> 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 

Tutaj jest to funkcja, która realizuje ten, umożliwiając łatwy specyfikacji centralny zespół

gamesplayed <- function(date, t1, t2, focal="DC") { 
    played <- t1 == focal | t2 == focal 
    o <- order(date, played) 
    cumsum(played[o])[order(o)] 
}