Как вставить значение 0 в набор данных временных рядов в Python (или SAS)? - PullRequest
2 голосов
/ 09 марта 2020

У меня есть набор данных следующим образом:

 device   occupancy          time          co2   humidity     ID
      A       1      2019-03-27 10:17:22  848.0  44.653748    1
      A       1      2019-03-27 10:17:22  848.0  44.653748    2
      B       1      2019-03-27 10:17:22  848.0  41.653748    3
      B       1      2019-03-27 10:17:22  848.0  41.653748    4
      C       1      2019-03-27 08:02:05  685.0  39.968201    5
      D       1      2019-03-27 12:16:53  793.0  35.641235    6

Как вы видите, набор данных содержит все записи, когда занятость (1) обнаружена, а 0 не записана. Мне нужно расширять его в новый набор данных каждые 15 минут. в то время как значение занятости должно быть либо 1, либо 0.

В SAS я пробовал следующее. работает только после удаления дубликатов:

 proc timeseries data = df1 ; 
 by ID;
 id time interval= Minute15 accumulate = max;
 var occupancy co2 humidity; 
 run;

Например, что я хочу (каждые 15 минут):

  occupancy         time             co2   ...
    1          25Mar19:07:24         616   ...
    0          25Mar19:07:49         0
    0          25Mar19:08:04         0
    ...        ....

В python Я также пытался (после удаления дубликатов):

time_first = df1['time'].min()  
time_last = df1['time'].max() 
mux = pd.MultiIndex.from_product(
     [pd.date_range(time_first, time_last, freq='H'), 
        df1['device'].unique()], names=['time', 'device'])
print (mux)

want = df1.set_index(['time', 'device']).reindex(mux, 
       fill_value=0).reset_index()

но сообщил об ошибке:

 "ValueError: cannot handle a non-unique multi-index!"

Может ли кто-нибудь помочь решить ее через Python (предпочтительно)?

Ответы [ 2 ]

1 голос
/ 09 марта 2020

Как упоминал Reeza в комментариях, один из способов сделать это - подготовить данные с помощью proc timeseries, используя опции start= и end=. Простой способ динамически получить начальные / конечные значения - это извлечь их из данных и заранее сохранить их в макропеременных.

proc sql noprint;
    select min(time) format=datetime.
         , max(time) format=datetime.
    into :mintime
       , :maxtime
    from have
    ;
quit;

proc timeseries data=have
                out=want;
    by id;

    id time interval   = minute15. 
            start      = "&mintime."dt 
            end        = "&maxtime."dt 
            accumulate = max 
            setmissing = 0
    ;

    var occupancy co2 humidity;
run;

Второй способ сделать это без получения минимальных / максимальных значений - сначала подготовка данных с помощью proc timeseries и последующая обработка через proc expand для заполнения пропущенных значений.

Данные в формате datalines приведены ниже.

data have;
    format time datetime.;
    infile datalines dlm=',';
    input device$ occupancy time:anydtdtm. co2 humidity id;
    datalines;
A,       1,      2019-03-27 10:17:22,  848.0,  44.653748,    1
A,       1,      2019-03-27 10:17:22,  848.0,  44.653748,    2
B,       1,      2019-03-27 10:17:22,  848.0,  41.653748,    3
B,       1,      2019-03-27 10:17:22,  848.0,  41.653748,    4
C,       1,      2019-03-27 08:02:05,  685.0,  39.968201,    5
D,       1,      2019-03-27 12:16:53,  793.0,  35.641235,    6
;
run;
0 голосов
/ 11 марта 2020
 proc timeseries data = df1 ; 
 by ID;
 id time interval= Minute15 accumulate = max;
 var occupancy co2 humidity; 
 run;
...