2016-08-14 3 views
0

У меня есть кадр данных df который имеет даты в нем:Панда: Петля через dataframe с вне счетчиком

df['Survey_Date'].head(4) 
Out[65]: 
0 1990-09-28 
1 1991-07-26 
2 1991-11-23 
3 1992-10-15 

Я заинтересован в вычислении метрики между двумя датами, с помощью отдельного кадра flow_df данных.

flow_df выглядит следующим образом:

 date flow 
0 1989-01-01 7480 
1 1989-01-02 5070 
2 1989-01-03 6410 
3 1989-01-04 10900 
4 1989-01-05 11700 

Например, я хотел бы запросить другой кадр данных на основе current_date и early_date. Первый период времени интереса будет:

current_date = 1991-07-26 
early_date = 1990-09-28 

Я написал неуклюжее цикл, и он получает работу, но я уверен, что есть более удобный способ:

Моего подхода со счетчиком и для петли:

def find_peak(early_date,current_date,flow_df): 
    mask = (flow_df['date']>= early_date) & (flow_df['date'] < current_date) 
    query = flow_df.loc[mask] 
    peak_flow = np.max(query['flow'])*0.3048**3 
    return peak_flow 

n=0 
for thing in df['Survey_Date'][1:]: 
    early_date = df['Survey_Date'][n] 
    current_date = thing 
    peak_flow = find_peak(early_date,current_date,flow_df) 
    n+=1 
    df['Avg_Stage'][n] = peak_flow 

Как это сделать без счетчика и для цикла?

Нужный результат выглядит так:

Survey_Date Avg_Stage 
0 1990-09-28 
1 1991-07-26 574.831986 
2 1991-11-23 526.693347 
3 1992-10-15 458.732915 
4 1993-04-01 855.168767 
5 1993-11-17 470.059653 
6 1994-04-07 419.089330 
7 1994-10-21 450.237861 
8 1995-04-24 498.376500 
9 1995-06-23 506.871554 
+0

Вы хотите выбрать период между 'early-date' и' current-date'? –

+0

да, но мой вопрос заключается в том, как пропустить кадр данных с датами интереса. – dubbbdan

+1

В вашем кадре данных между «ранними датами» и «текущей датой» нет ничего. Можете ли вы опубликовать желаемый результат? –

ответ

2

Вы можете определить новая переменная, которая определяет период обследования и использует pandas.DataFrame.groupby, чтобы избежать for петля. Он должен быть намного быстрее, когда flow_df большой.

#convert both to datetime, if they are not 
df['Survey_Date'] = pd.to_datetime(df['Survey_Date']) 
flow_df['date'] = pd.to_datetime(flow_df['date']) 

#Merge Survey_Date to flow_df. Most rows of flow_df['Survey_Date'] should be NaT 
flow_df = flow_df.merge(df, left_on='date', right_on='Survey_Date', how='outer') 

# In case not all Survey_Date in flow_df['date'] or data not sorted by date. 
flow_df['date'].fillna(flow_df['Survey_Date'], inplace=True) 
flow_df.sort_values('date', inplace=True) 

#Identify survey period. In your example: [1990-09-28, 1991-07-26) is represented by 0; [1991-07-26, 1991-11-23) = 1; etc. 
flow_df['survey_period'] = flow_df['Survey_Date'].notnull().cumsum() 

#calc Avg_Stage in each survey_period. I did .shift(1) because you want to align period [1990-09-28, 1991-07-26) to 1991-07-26 
df['Avg_Stage'] = (flow_df.groupby('survey_period')['flow'].max()*0.3048**3).shift(1) 
+0

Это именно то, что я искал! 'flow_df' довольно большой, а для операторов неудобны. Благодаря! – dubbbdan

0

Вы можете использовать zip():

for early_date, current_date in zip(df['Survey_Date'], df['Survey_Date'][1:]): 
    #do whatever yo want. 

Конечно, вы можете поместить его в список понимания:

[some_metric(early_date, current_date) for early_date, current_date in zip(df['Survey_Date'], df['Survey_Date'][1:])] 
+0

Ницца, это становится ближе к тому, что я за ним. – dubbbdan

+1

Если бы вы пожелали больше, вам нужно быть более точным в своем вопросе –

+0

Я думал просто сказать, что я не хочу использовать цикл for, было бы достаточно деталей, но я вернулся и отредактировал свое оригинальное сообщение, чтобы включить более подробную информацию. – dubbbdan

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