2014-10-04 10 views
5

Mam znacznie większą istniejącą ramkę danych. Dla tego mniejszego przykładu chciałbym zastąpić niektóre zmienne (zamień stan (df1)) na newstate (df2) zgodnie z kolumną "first". Mój problem polega na tym, że wartości są zwracane jako NA, ponieważ tylko niektóre nazwy są dopasowywane w nowej ramce danych (df2).Mieć wartość zwracaną przez nomatch, używając funkcji dopasowywania w R

Istniejące dataframe:

state = c("CA","WA","OR","AZ") 
first = c("Jim","Mick","Paul","Ron") 
df1 <- data.frame(first, state) 

     first state 
    1 Jim CA 
    2 Mick WA 
    3 Paul OR 
    4 Ron AZ 

New dataframe dopasować do istniejących dataframe

state = c("CA","WA") 
newstate = c("TX", "LA") 
first =c("Jim","Mick") 
df2 <- data.frame(first, state, newstate) 

    first state newstate 
1 Jim CA  TX 
2 Mick WA  LA 

próbował użyć mecz, ale zwraca NA dla "państwa", w którym dopasowanie "pierwszy" zmienna z df2 nie jest znalezione w oryginalnej ramce danych.

df1$state <- df2$newstate[match(df1$first, df2$first)] 

    first state 
1 Jim TX 
2 Mick LA 
3 Paul <NA> 
4 Ron <NA> 

Czy istnieje sposób, aby zignorować nomatch lub zmusić nomatch do zwrotu istniejącej zmiennej tak jak jest? Byłby to przykład pożądanego rezultatu: stany Jim/Mick są aktualizowane, podczas gdy stan Paula i Rona nie ulega zmianie.

 first state 
    1 Jim TX 
    2 Mick LA 
    3 Paul OR 
    4 Ron AZ 

Odpowiedz

6

Czy tego chcesz; BTW, chyba że naprawdę chcesz pracować z czynnikami, użyj stringówAsFactors = FALSE w wywołaniu data.frame. Zwróć uwagę na użycie nomatch = 0 w wywołaniu meczu.

> state = c("CA","WA","OR","AZ") 
> first = c("Jim","Mick","Paul","Ron") 
> df1 <- data.frame(first, state, stringsAsFactors = FALSE) 
> state = c("CA","WA") 
> newstate = c("TX", "LA") 
> first =c("Jim","Mick") 
> df2 <- data.frame(first, state, newstate, stringsAsFactors = FALSE) 
> df1 
    first state 
1 Jim CA 
2 Mick WA 
3 Paul OR 
4 Ron AZ 
> df2 
    first state newstate 
1 Jim CA  TX 
2 Mick WA  LA 
> 
> # create an index for the matches 
> indx <- match(df1$first, df2$first, nomatch = 0) 
> df1$state[indx != 0] <- df2$newstate[indx] 
> df1 
    first state 
1 Jim TX 
2 Mick LA 
3 Paul OR 
4 Ron AZ 
+0

Twój kod działa. [Dziękuję.] Ale czy możesz wyjaśnić, dlaczego masz' indx! = 0' po lewej stronie równych i 'indx' na prawa strona równości? 'df1 $ state [indx! = 0] <- df2 $ newstate [indx]' –

2
library(data.table) 
DT1 <- as.data.table(df1) 
DT2 <- as.data.table(df2) 


setkey(DT1, first, state) 
setkey(DT2, first, state) 

DT1[DT2] 
# first state newstate 
# 1: Jim CA  TX 
# 2: Mick WA  LA 

Zauważ, że [.data.table posiada również nomatch argumentem, tj:

DT2[DT1, nomatch=0] 
# first state newstate 
# 1: Jim CA  TX 
# 2: Mick WA  LA 

DT2[DT1, nomatch=NA] 
# first state newstate 
# 1: Jim CA  TX 
# 2: Mick WA  LA 
# 3: Paul OR  NA 
# 4: Ron AZ  NA 

3

myślę, że będzie można uzyskać lepsze zachowanie z wektorami znaków niż z czynników.

> df1 <- data.frame(first, state,stringsAsFactors=FALSE) 
> state = c("CA","WA") 
> newstate = c("TX", "LA") 
> first =c("Jim","Mick") 
> df2 <- data.frame(first, state, newstate, stringsAsFactors=FALSE) 
> df1[ match(df2$first, df1$first), "state"] <- df2$newstate 
> df1 
    first state 
1 Jim TX 
2 Mick LA 
3 Paul OR 
4 Ron AZ 
+0

Udało mi się odtworzyć odpowiedź. Następnie przekonwertowałem moje oryginalne dane, wszystkie na znaki i sprawdzone formaty za pomocą polecenia str(). Wydaje się, że mają identyczną strukturę. Gdy próbuję, wypróbuję na większym, oryginalnym zbiorze danych, otrzymam: "Błąd w' [<-. Data.frame' ('* tmp *', dopasowanie (najpierw df2 $, pierwsze df1), : brakujące wartości nie są dozwolone w indeksowanych przypisaniach ramek danych " – panstotts

Powiązane problemy