简体   繁体   中英

First value of each week in pd.Series/DataFrame

Say I have a pd.Series of daily S&P 500 values, and I would like to filter this series to get the first business day and the associated value of each week.

So, for instance, my filtered series would contain the 5 September 2017 (Tuesday - no value for the Monday), then 11 September 2017 (Monday).

Source series: 
2017-09-01    2476.55
2017-09-05    2457.85
2017-09-06    2465.54
2017-09-07    2465.10
2017-09-08    2461.43
2017-09-11    2488.11
2017-09-12    2496.48

Filtered series
2017-09-01    2476.55
2017-09-05    2457.85
2017-09-11    2488.11

My solution currently consists of:

mask     = SP500.apply(lambda row: SP500[row.name - datetime.timedelta(days=row.name.weekday()):].index[0], axis=1).unique()
filtered = SP500.loc[mask]

This however feels suboptimal/non-pythonic. Any better/faster/cleaner solutions?

df.sort_index().assign(week=df.index.get_level_values(0).week).drop_duplicates('week',keep='first').drop('week',1)
Out[774]: 
              price
2017-09-01  2476.55
2017-09-05  2457.85
2017-09-11  2488.11

Using resample on pd.Series.index.to_series

s[s.index.to_series().resample('W').first()]

2017-09-01    2476.55
2017-09-05    2457.85
2017-09-11    2488.11
dtype: float64

I'm not sure that the solution you give works, since the .apply method for series can't access the index, and doesn't have an axis argument. What you gave would work on a DataFrame, but this is simpler if you have a dataframe:

#Make some fake data
x = pd.DataFrame(pd.date_range(date(2017, 10, 9), date(2017, 10, 23)), columns = ['date'])
x['value'] = x.index
print(x)
         date  value
0  2017-10-09      0
1  2017-10-10      1
2  2017-10-11      2
3  2017-10-12      3
4  2017-10-13      4
5  2017-10-14      5
6  2017-10-15      6
7  2017-10-16      7
8  2017-10-17      8
9  2017-10-18      9
10 2017-10-19     10
11 2017-10-20     11
12 2017-10-21     12
13 2017-10-22     13
14 2017-10-23     14

#filter
filtered = x.groupby(x['date'].apply(lambda d: d-timedelta(d.weekday())), as_index = False).first()
print(filtered)
        date  value
0 2017-10-09      0
1 2017-10-16      7
2 2017-10-23     14

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM