2014-10-04 12 views
5

У меня есть гораздо больший существующий dataframe. Для этого небольшого примера я хотел бы заменить некоторые из переменных (replace state (df1)) на newstate (df2) в соответствии с первым столбцом. Моя проблема заключается в том, что значения возвращаются как NA, так как только некоторые из имен сопоставляются в новом фрейме данных (df2).Имейте номенклатурное возвращаемое значение as-is, используя функцию соответствия в R

Существующие 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 

Новый dataframe в соответствии с существующими 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 

Пытались использовать матч, но возвращает NA для "государства", где совпадающий "первый" переменная из df2 не найденный в исходном фрейме данных.

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

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

Есть ли способ игнорировать номограмму или возвращать номенклатуру существующей переменной как есть? Это будет пример желаемого результата: состояния Джима/Мика обновляются, а состояние Пола и Рона не меняется.

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

ответ

6

Это то, что вы хотите; BTW, если вы действительно не хотите работать с факторами, используйте stringAsFactors = FALSE в вашем вызове data.frame. Обратите внимание на использование nomatch = 0 в совпадении.

> 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

Ваш код работает. [Спасибо.] Но можете ли вы объяснить, почему у вас есть' indx! = 0' в левой части равных и 'indx' on правая часть равен? '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 

Обратите внимание, что [.data.table также имеет nomatch аргумент, а именно:

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

Я думаю, что вы получите лучшее поведение с векторами символов, чем с факторами.

> 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

Я смог воспроизвести ваш ответ. Затем я преобразовал исходные данные, все в символы и проверенные форматы с помощью str(). Они кажутся одинаковыми по своей структуре. Когда я пытаюсь попробовать это на моем более крупном исходном наборе данных, я получаю это: «Ошибка в' [<-. Data.frame' ('* tmp *', match (сначала df2 $, сначала df1 $) : Недопустимые значения недопустимы для индексированных присвоений кадров данных « – panstotts

 Смежные вопросы

  • Нет связанных вопросов^_^