2016-06-09 3 views
8

Это образец моих данных из CSV. Он содержит ~ 10 столбцов.Заменить NA с предыдущим вхождением

Product_id Product_Weight Product_Name Shop_Name ... 
[1] A    10    xxxx   Walmart 
[2] B    12    yyyy   Target 
[3] C    11    zzzz   Target 
[4] A    NA    xxxx   Walmart 
[5] C    NA    zzzz   Target 

Я хотел бы, чтобы заполнить числовые апертуры в строке 4 и 5 с 10 и 11 соответственно (так как вес продукта А и С уже известны из строки 1 и 3). Я хочу, чтобы конечная рамка данных была такой:

Product_id Product_Weight Product_Name Shop_Name ... 
[1] A    10    xxxx   Walmart 
[2] B    12    yyyy   Target 
[3] C    11    zzzz   Target 
[4] A    10    xxxx   Walmart 
[5] C    11    zzzz   Target 

Каков наилучший способ сделать это в R?

+0

Эти весы всегда установлены так, что комбинация Product_id - Product_name вернет тот же вес? – lmo

+0

@ lmo Да, они есть. – Avis

+0

Другие вопросы и ответы о замене NA: http://stackoverflow.com/questions/32694313/handle-continous-missing-values-in-time-series-data – Jaap

ответ

5

Другой вариант с dplyr и tidyr:

library(dplyr); library(tidyr); 
df %>% group_by(Product_id) %>% fill(Product_Weight) 

Source: local data frame [5 x 4] 
Groups: Product_id [3] 

    Product_id Product_Weight Product_Name Shop_Name 
     (fctr)   (int)  (fctr) (fctr) 
1   A    10   xxxx Walmart 
2   A    10   xxxx Walmart 
3   B    12   yyyy Target 
4   C    11   zzzz Target 
5   C    11   zzzz Target 

Результат сортировки по Product_id.

+0

cant dplyr сделать это без переупорядочения? – rawr

9

Хотя вопрос, заданный для «предыдущего вхождения» это будет иметь тот недостаток, что если первый Product_Weight в любом Product_id был NA, то она не может быть заполнена в, даже если бы мы знали Product_Weight от последующего Product_id поэтому вместо того, чтобы использовать в предыдущем случае мы принимаем среднее значение всех не-NA с тем же Product_id. Так как все они должны быть одинаковыми, то их средняя их общая ценность.

Если вы действительно хотите предыдущее вхождение использовать функцию Prev где:

Prev <- function(x) na.locf(x, na.rm = FALSE) 

вместо na.aggregate в (1) и (3) и не использовать (2).

следующие решения имеют те преимущества, что все они:

  • сохраняющие порядок ввода

  • работа, даже если в какой-либо Product_id первый Product_Weight является Н.

  • не изменить вход

Первое решение имеет дополнительное преимущество только в одной строке кода (плюс заявление library), а второе решение имеет дополнительное преимущество, заключающееся в том, что вы не используете какие-либо пакеты.

1) зоопарк :: na.aggregate Мы используем na.aggregate в пакете зоопарка (который заменяет все Nas со средним не-НСБУ) и применить его к Product_Weight отдельно для каждого Product_id.

library(zoo) 
transform(DF, Product_Weight = ave(Product_Weight, Product_id, FUN = na.aggregate)) 

дает:

Product_id Product_Weight Product_Name Shop_Name 
1   A    10   xxxx Walmart 
2   B    12   yyyy Target 
3   C    11   zzzz Target 
4   A    10   xxxx Walmart 
5   C    11   zzzz Target 

2) Нет пакетов Поочередно использовать Mean вместо na.aggregate где Mean определяется как:

Mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE)) 

3) dplyr/зоопарк Добавить номера строк, группы по Product_id, заполните NAs как и в предыдущих решениях с использованием либо na.aggregate, как показано ниже, или Mean, организовать обратно к первоначальному порядку и удалить номера строк:

library(dplyr) 
library(zoo) 

DF %>% 
    mutate(row = row_number()) %>% 
    group_by(Product_id) %>% 
    mutate(Product_Weight = na.aggregate(Product_Weight)) %>% 
    ungroup() %>% 
    arrange(row) %>% 
    select(-row) 

Примечание: Это было использовано для ввода DF:

Lines <- " Product_id Product_Weight Product_Name Shop_Name 
    A    10    xxxx   Walmart 
    B    12    yyyy   Target 
    C    11    zzzz   Target 
    A    NA    xxxx   Walmart 
    C    NA    zzzz   Target" 
DF <- read.table(text = Lines, header = TRUE) 
2

Здесь решение с базой команд R:

# create lookup table with item and weight combinations 
lookup<-unique(df[complete.cases(df[ ,1:2]),]) 

#  find the NAs needing replacement: which(is.na(df$weight)) 
#  find index in lookup tabe:match(df$a[which(is.na(df$weight)) 
#  subset: df$weight[which(is.na(df$weight)) 
df$weight[which(is.na(df$weight))]<-lookup$weight[match(df$Product_id[which(is.na(df$weight))], lookup$Product_id)] 

Скорее всего, не так эффективно, как dplyr/tidyr раствора, упомянутого выше.

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