pandas 从每日数据dataframe获取上周数据

p8h8hvxi  于 2023-04-18  发布在  其他
关注(0)|答案(2)|浏览(129)

我有两个 Dataframe df 1包含每日数据
| 日期|工作日|高|低|
| --------------|--------------|--------------|--------------|
| 2016年1月1日|星期五|17144.85|一六八二三|
| 2016年1月4日|星期一|一万七千|16603|
| 2016年1月5日|星期二|一六七○ ○|16516.65|
| 2016年1月6日|星期三|16659.3|16376|
| 2016年1月7日|星期四|16344.4|16058|
| 2016年1月8日|星期五|16264|16126.05|
| 2016年1月11日|星期一|16186|15841.4|
| 2016年1月12日|星期二|16125.3|15723.3|
| 2016年1月13日|星期三|15974|15536|
| 2016年1月14日|星期四|15808.7|15455|
| 2016年1月15日|星期五|15639|15161.5|
| 2016年1月18日|星期一|15347|14985.35|
| 2016年1月19日|星期二|15348|15083.65|
| 2016年1月20日|星期三|15060|一四七三○|
| 2016年1月21日|星期四|15360|14901|
| 2016年1月22日|星期五|15607.8|15261|
| 2016年1月25日|星期一|15681.3|15460|
| 2016年1月27日|星期三|15629.2|15412.65|
| 2016年1月28日|星期四|15564.9|15355|
| 2016年1月29日|星期五|一五五七八|15171.6|
我想做的是基于df 1需要创建一个新的dataframe并存储所选周的前一周累积的高和低。
对于“当前周高”和“当前周低”(CWH和CWL)列,它以一种方式存储一周中每个日期的当前周高/低,一周中的每个日期保持像Max(周的开始日期,周的选定日期)这样的值,并将一周中的每个开始日期标记为“无”

**例如:**让我们取第1周是1月4日至1月8日,第2周是1月11日至1月15日,第1周没有任何前一周,因此在新的数据框中,从第4日到第8日的所有日期将在前一个高/低列中保持无。第2周前一周是第1周,因此第2周的所有日期将保持最大高和最小低。

当前CWH和CWL:在第1周中,4th jan是一周的开始日,因此标记为None,5th Jan是max(4th,5th),6 th jan max(4th,6 th),所有周以此类推
预期输出:
| 日期|PWH|PWL|CWH|CWL|
| --------------|--------------|--------------|--------------|--------------|
| 2016年1月1日|- -|- -|- -|- -|
| 2016年1月4日|17144.85|一六八二三|- -|- -|
| 2016年1月5日|17144.85|一六八二三|一万七千|16603|
| 2016年1月6日|17144.85|一六八二三|一万七千|16516.65|
| 2016年1月7日|17144.85|一六八二三|一万七千|16376|
| 2016年1月8日|17144.85|一六八二三|一万七千|16058|
| 2016年1月11日|一万七千|16058|- -|- -|
| 2016年1月12日|一万七千|16058|16186|15841.4|
| 2016年1月13日|一万七千|16058|16186|15723.3|
| 2016年1月14日|一万七千|16058|16186|15536|
| 2016年1月15日|一万七千|16058|16186|15455|
| 2016年1月18日|16186|15161.5|- -|- -|
| 2016年1月19日|16186|15161.5|15347|14985.35|
| 2016年1月20日|16186|15161.5|15348|14985.35|
| 2016年1月21日|16186|15161.5|15348|一四七三○|
| 2016年1月22日|16186|15161.5|15360|一四七三○|
| 2016年1月25日|15607.8|一四七三○|- -|- -|
| 2016年1月27日|15607.8|一四七三○|15681.3|15460|
| 2016年1月28日|15607.8|一四七三○|15681.3|15412.65|
| 2016年1月29日|15607.8|一四七三○|15681.3|15355|
尝试了这个代码:

temp_wk = daily_df.copy()
temp_wk.set_index(pd.to_datetime(temp_wk['Date']), inplace=True)

weekly_high = temp_wk['Low'].resample('W').min()

prev_week_high = weekly_high.shift(1)

print(prev_week_high)

但这并没有给出可接受的产出。

piok6c0g

piok6c0g1#

IIUC,这应该可以实现你想要的:

new_df = pd.DataFrame({'Date': daily_df['Date'], 'PWH': None, 'PWL': None, 'CWH': None, 'CWL': None})

new_df['Date'] = pd.to_datetime(new_df['Date'])
new_df['Week'] = new_df['Date'].dt.week

# Compute the cumulative high and low for the previous week, and fill in the appropriate values
for week in new_df['Week'].unique():
    if week == new_df['Week'].min():
        # Skip the first week, since there is no previous week
        continue
    prev_week_mask = new_df['Week'] == (week - 1)
    curr_week_mask = new_df['Week'] == week
    prev_week_high = daily_df.loc[prev_week_mask, 'High'].max()
    prev_week_low = daily_df.loc[prev_week_mask, 'Low'].min()
    new_df.loc[curr_week_mask, 'PWH'] = prev_week_high
    new_df.loc[curr_week_mask, 'PWL'] = prev_week_low

# Compute the current week high and low, and fill in the appropriate values
for week in new_df['Week'].unique():
    week_mask = new_df['Week'] == week
    start_date = new_df.loc[week_mask, 'Date'].min()
    for i, row in new_df.loc[week_mask].iterrows():
        if row['Date'] == start_date:
            # For the starting date of the week, set the current week high and low to None
            new_df.loc[i, 'CWH'] = None
            new_df.loc[i, 'CWL'] = None
        else:
            # For other dates in the week, set the current week high and low to the max/min of the previous values and the current values
            prev_high = new_df.loc[i-1, 'CWH']
            prev_low = new_df.loc[i-1, 'CWL']
            curr_high = daily_df.loc[daily_df['Date'] == row['Date'], 'High'].values[0]
            curr_low = daily_df.loc[daily_df['Date'] == row['Date'], 'Low'].values[0]
            new_df.loc[i, 'CWH'] = max(prev_high, curr_high)
            new_df.loc[i, 'CWL'] = min(prev_low, curr_low)

# Drop the Week column to match expected output
new_df.drop(columns=['Week'], inplace=True)
6vl6ewon

6vl6ewon2#

这是我的解决方案

df['Date'] = pd.to_datetime(df['Date'])
df = df.set_index('Date').sort_index()

#compute weekly min and max
week_max = df.resample('W')['High'].max()
week_min = df.resample('W')['Low'].min()

#compute weekly min and max
max_min = (df.resample('W')[['High', 'Low']]
           .agg({'High': 'max', 'Low': 'min'})
           .rename({'Low': 'PWL', 'High':'PWH'}, axis=1)
           .shift(1)
           )
max_min.index = max_min.index - timedelta(weeks=1)

#merge_asof will perform a join based on the closest date, in the backward direction
df = pd.merge_asof(df, max_min, left_index=True, right_index=True, direction='backward')

#compute cumulative min and max in each week
df[['year','week', 'day']] = df.index.isocalendar()
#we also group by year in case we have multi-year data

#set `CWH` and `CWL` to the `High` and `Low` value of the first day of the week
df['CWH'] = df.groupby(['year','week'])['High'].transform('first')
df['CWL'] = df.groupby(['year','week'])['Low'].transform('first')

#perform max and min between the first day and current day
df['CWH'] = df[['High','CWH']].max(axis=1)
df['CWL'] = df[['Low','CWL']].min(axis=1)

#removing the first day of each week (weekdays were already sorted for merge_asof)
df.loc[df.groupby(['year','week']).head(1).index, ['CWH', 'CWL']] = None
df = df.drop(['High', 'Low', 'year', 'week', 'day', 'Week Day'], axis=1)

相关问题