2016-10-18 2 views
0

この問題の解決策を見つけるためには、私はたくさんの掘り起こしが必要でした。この問題を解決するためのよりよい方法を知りたいのですが、私はまだ国境問題を解決する必要があることを考慮に入れています。Python:パンダのDataFrameを時間、曜日、月別にフィルタリングする

私は、2009年から2012年までの「パワー」の10小単位のセットを持っており、すべての年の時間と日/月のウィンドウを取得したいとします(つまり、時間、日、月ごとのフィルタリング)。次のように私があるようになった何

:出力として返す

import pandas as pd 
import numpy as np 
import datetime 

dates = pd.date_range(start="08/01/2009",end="08/01/2012",freq="10min") 
df = pd.DataFrame(np.random.rand(len(dates), 1)*1500, index=dates, columns=['Power']) 

def filter(df, day, month, hour, daysWindow, hoursWindow): 
    """ 
    Filter a Dataframe by a date window and hour window grouped by years 

    @type df: DataFrame 
    @param df: DataFrame with dates and values 

    @type day: int 
    @param day: Day to focus on 

    @type month: int 
    @param month: Month to focus on 

    @type hour: int 
    @param hour: Hour to focus on 

    @type daysWindow: int 
    @param daysWindow: Number of days to perform the days window selection 

    @type hourWindow: int 
    @param hourWindow: Number of hours to perform the hours window selection 

    @rtype: DataFrame 
    @return: Returns a DataFrame with the 
    """ 
    df_filtered = None 
    grouped = df.groupby(lambda x : x.year) 
    for year, groupYear in grouped: 
     groupedMonthDay = groupYear.groupby(lambda x : (x.month, x.day)) 
     for monthDay, groupMonthDay in groupedMonthDay: 
      if monthDay >= (month,day - daysWindow) and monthDay <= (month,day + daysWindow): 
       new_df = groupMonthDay.ix[groupMonthDay.index.indexer_between_time(datetime.time(hour - hoursWindow), datetime.time(hour + hoursWindow))] 
       if df_filtered is None: 
        df_filtered = new_df 
       else: 
        df_filtered = df_filtered.append(new_df) 
    return df_filtered 

df_filtered = filter(df,day=8, month=10, hour=8, daysWindow=1, hoursWindow=1) 
print len(df) 
print len(df_filtered) 

:もちろん

>>> 
157825 
117 

は改善があるだろうのような時間を選択する際に国境問題に関するこのコードのニーズ1とhoursWindow 2です。つまり、

>>> filter(df,day=8, month=10, hour=1, daysWindow=1, hoursWindow=2) 
Traceback (most recent call last): 
    File "<interactive input>", line 1, in <module> 
    File "D:\tmp\test_filtro.py", line 40, in filter 
    new_df = groupMonthDay.ix[groupMonthDay.index.indexer_between_time(datetime.time(hour - hoursWindow), datetime.time(hour + hoursWindow))] 
ValueError: hour must be in 0..23 

同様の問題は、 1または30のように。

このコードはどのように改善できますか? filter関数の

答えて

0

更新されたコードには国境問題はありませんが保証:

import pandas as pd 
import numpy as np 
import datetime 

dates = pd.date_range(start="08/01/2009",end="08/01/2012",freq="10min") 
df = pd.DataFrame(np.random.rand(len(dates), 1)*1500, index=dates, columns=['Power']) 

def filter(df, day, month, hour, minute=0, daysWindow=1, hoursWindow=1): 
    """ 
    Filter a Dataframe by a date window and hour window grouped by years 

    @type df: DataFrame 
    @param df: DataFrame with dates and values 

    @type day: int 
    @param day: Day to focus on 

    @type month: int 
    @param month: Month to focus on 

    @type hour: int 
    @param hour: Hour to focus on 

    @type daysWindow: int 
    @param daysWindow: Number of days to perform the days window selection 

    @type hoursWindow: int 
    @param hourWindow: Number of hours to perform the hours window selection 

    @rtype: DataFrame 
    @return: Returns a DataFrame with the 
    """ 
    df_filtered = None 
    grouped = df.groupby(lambda x : x.year) 
    for year, groupYear in grouped: 
     date = datetime.date(year, month, day) 
     dateStart = date - datetime.timedelta(days=daysWindow) 
     dateEnd = date + datetime.timedelta(days=daysWindow+1) 
     df_filtered_days = df[dateStart:dateEnd] 
     timeStart = datetime.time(0 if hour-hoursWindow < 0 else hour-hoursWindow, minute) 
     timeEnd = datetime.time(23 if hour+hoursWindow > 23 else hour+hoursWindow, minute) 
     new_df = df_filtered_days.ix[df_filtered_days.index.indexer_between_time(timeStart, timeEnd)] 
     if df_filtered is None: 
      df_filtered = new_df 
     else: 
      df_filtered = df_filtered.append(new_df) 
    return df_filtered 

df_filtered = filter(df,day=8, month=10, hour=1, daysWindow=1, hoursWindow=2) 
print len(df) 
print len(df_filtered) 

出力は次のとおりです。

>>> 
157825 
174 
関連する問題