2015-05-15 12 views
6

Moja ramka danych składa się z osób i miasta, w którym żyją w określonym momencie. Chciałbym wygenerować jedną matrycę miejsce docelowe dla każdego roku, która rejestruje liczbę ruchów z jednego miasta do drugiego. Chciałbym wiedzieć:Tworzenie macierzy miejsca docelowego z R

  1. Jak automatycznie wygenerować tabele miejsca pochodzenia dla każdego roku w moim zestawie danych?
  2. Jak mogę wygenerować wszystkie tabele w tym samym formacie 5x5, 5 to liczba miast w moim przykładzie?
  3. Czy istnieje skuteczniejszy kod niż ten, który proponuję poniżej? Zamierzam uruchomić go na bardzo dużym zbiorze danych.

Rozważmy następujący przykład:

#An example dataframe 
id=sample(1:5,50,T) 
year=sample(2005:2010,50,T) 
city=sample(paste(rep("City",5),1:5,sep=""),50,T) 
df=as.data.frame(cbind(id,year,city),stringsAsFactors=F) 
df$year=as.numeric(df$year) 
df=df[order(df$id,df$year),] 
rm(id,year,city) 

My najlepiej spróbować

#Creating variables 
for(i in 1:length(df$id)){ 
    df$origin[i]=df$city[i] 
    df$destination[i]=df$city[i+1] 
    df$move[i]=ifelse(df$orig[i]!=df$dest[i] & df$id[i]==df$id[i+1],1,0) #Checking whether a move has taken place and whether its the same person 
    df$year_move[i]=ceiling((df$year[i]+df$year[i+1])/2) #I consider that the person has moved exactly between the two dates at which its location was recorded 
} 
df=df[df$move!=0,c("origin","destination","year_move")]  

Tworzenie tabeli origin-docelowy dla 2007

yr07=df[df$year_move==2007,] 
table(yr07$origin,yr07$destination) 

Wynik

 City1 City2 City3 City5 
    City1  0  0  1  2 
    City2  2  0  0  0 
    City5  1  1  0  0 
+2

Jeśli przedstawiający wyjście z danych symulowanych, to najlepiej użyć 'set.seed' przed symulacji (tak że wszyscy patrzymy na to samo). – Frank

Odpowiedz

6

Możesz podzielić dane z przez ID, wykonaj niezbędne obliczenia na ramce danych id specyficzne chwycić wszystkie ruchy od tej osoby, a następnie ponownie połączyć:

spl <- split(df, df$id) 
move.spl <- lapply(spl, function(x) { 
    ret <- data.frame(from=head(x$city, -1), to=tail(x$city, -1), 
        year=ceiling((head(x$year, -1)+tail(x$year, -1))/2), 
        stringsAsFactors=FALSE) 
    ret[ret$from != ret$to,] 
}) 
(moves <- do.call(rbind, move.spl)) 
#  from to year 
# 1.1 City4 City2 2007 
# 1.2 City2 City1 2008 
# 1.3 City1 City5 2009 
# 1.4 City5 City4 2009 
# 1.5 City4 City2 2009 
# ... 

Ponieważ tego kodu używa wektorowych obliczeń dla każdego identyfikatora, powinno to być znacznie szybsze niż przechodzenie przez każdy wiersz ramki danych, tak jak w podanym kodzie.

Teraz można chwycić roku specyficzne macierze 5x5 poruszać się za pomocą split i table:

moves$from <- factor(moves$from) 
moves$to <- factor(moves$to) 
lapply(split(moves, moves$year), function(x) table(x$from, x$to)) 
# $`2005` 
#   
#   City1 City2 City3 City4 City5 
# City1  0  0  0  0  1 
# City2  0  0  0  0  0 
# City3  0  0  0  0  0 
# City4  0  0  0  0  0 
# City5  0  0  1  0  0 
# 
# $`2006` 
#   
#   City1 City2 City3 City4 City5 
# City1  0  0  0  1  0 
# City2  0  0  0  0  0 
# City3  1  0  0  1  0 
# City4  0  0  0  0  0 
# City5  2  0  0  0  0 
# ... 
+0

Bardzo dobra dyskusja i dobra odpowiedź od @josliber. Zastanawiam się, czy możliwe jest posiadanie tylko jednego stołu na końcu, podsumowującego wszystkie lata. Edytowałem ostatnie polecenie zaproponowane przez Joslibera z 'a <- table (przenosi $ z, przenosi do $), ale mogę uzyskać ostateczny stół. żebym mógł napisać.csv! Jakieś pomysły? – Floni

+0

@Floni To jest po prostu 'table (przenosi $ from, moves $ to)'. Jeśli to nie działa, powinieneś zadać nowe pytanie za pomocą przycisku "Zadaj pytanie". – josliber