2016-02-12 3 views
4

У меня есть Данные о ценах, индексированные в соответствии с тремя вещами:Заполнение тонны данных NA в R по индексам?

Состояние, дата и UPC (это код продукта).

У меня есть куча цен, которые являются NA.

Я пытаюсь заполнить НС следующим образом: для данной отсутствует Цена с индексом (S, D, UPC), заполните среднюю цену всех точек данных с теми же S и UPC. I.e, возьмите среднее значение по дате.

Должен быть невероятно простой способ сделать это, потому что это очень просто. Я использую для циклов, но теперь понимаю, что это невероятно неэффективно, и я хотел бы использовать функцию, например, одну в plyr или dplyr, которая сделает все это как можно меньше.

upc=c(1153801013,1153801013,1153801013,1153801013,1153801013,1153801013,2105900750,2105900750,2105900750,2105900750,2105900750,2173300001,2173300001,2173300001,2173300001) 
date=c(200601,200602,200603,200604,200601,200602,200601,200602,200603,200601,200602,200603,200604,200605,200606) 
price=c(26,28,NA,NA,23,24,85,84,NA,81,78,24,19,98,NA) 
state=c(1,1,1,1,2,2,1,1,2,2,2,1,1,1,1) 

# This is what I have: 
data <- data.frame(upc,date,state,price) 

# This is what I want: 
price=c(26,28,27,27,23,24,85,84,79.5,81,78,24,19,98,47) 
data2 <- data.frame(upc,date,state,price) 

Любой совет? Благодарю.

+0

Извините, что я новичок в этом ... Я был бы признателен, если бы вы просто сказали мне, что я сделал неправильно, а не пассивные агрессивные ссылки и большие пальцы. – ejn

+1

@ejn - это не пассивный агрессивный, эти вопросы кратко описывают, что вам нужно, чтобы люди могли дать вам разумный ответ. Это, по сути, «правила» Stackoverflow, которые помогут нам вам помочь. – thelatemail

+0

Я создаю фальшивый dataframe, чтобы показать вам, что я имею в виду ... Я ценю терпение, я сделаю это в моменте. – ejn

ответ

8

Использование ave с несколькими переменными группирования, а затем заменить NA значения с помощью:

with(data, 
    ave(price, list(upc,state), FUN=function(x) replace(x,is.na(x),mean(x,na.rm=TRUE))) 
) 
# [1] 26.0 28.0 27.0 27.0 23.0 24.0 85.0 84.0 79.5 81.0 78.0 24.0 19.0 98.0 47.0 
6

Вы можете построить матрицу средств СКП и государства:

meanmtx <- tapply(dat$price, dat[c('upc','state')], mean, na.rm=TRUE) 

Эта матрица имеет характер индексы, которые могут быть сопоставлены с значениями в upc и state. Таким образом, а затем использовать 2 колонки индексации символов, чтобы поместить их в пустых «слотов»:

dat$price[is.na(dat$price)] <- 
      meanmtx[ cbind(as.character(dat[ is.na(dat$price), 'upc']), 
          as.character(dat[ is.na(dat$price),'state'])) ] 

> dat 
      upc date state price 
1 1153801013 200601  1 26.0 
2 1153801013 200602  1 28.0 
3 1153801013 200603  1 27.0 
4 1153801013 200604  1 27.0 
5 1153801013 200601  2 23.0 
6 1153801013 200602  2 24.0 
7 2105900750 200601  1 85.0 
8 2105900750 200602  1 84.0 
9 2105900750 200603  2 79.5 
10 2105900750 200601  2 81.0 
11 2105900750 200602  2 78.0 
12 2173300001 200603  1 24.0 
13 2173300001 200604  1 19.0 
14 2173300001 200605  1 98.0 
15 2173300001 200606  1 47.0 
4

Вот еще один компактный вариант с использованием na.aggregate (от zoo) и data.table. na.aggregate по умолчанию заменяет значения NA знаком mean интересующей колонки. У него также есть аргумент , если мы хотим заменить NA на median, min или max, или что бы мы ни пожелали. Группу по операциям можно выполнять с помощью методов dplyr/data.table/base R. С data.table мы преобразуем «data.frame» в «data.table» (setDT(data)), сгруппированные по «upc», «state», мы назначаем (:=) «цену» как na.aggregate «цены».

library(data.table) 
library(zoo) 
setDT(data)[, price:= na.aggregate(price) , .(upc, state)] 
Смежные вопросы