判断一个日期是否在一个期间内pandas

本文介绍了一种使用Pandas库进行数据筛选的新方法,通过两次.loc操作实现复合条件的筛选,并详细展示了如何去除指定范围内的数据,最后通过删除None值完成数据清洗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新方法:

用一个.loc也是可行的,连接的不是and ,是别的!!!!

去除的方法把不符合条件的变成None值,然后就可以了。

import pandas as pd

df  = pd.DataFrame([1,2,3,4,5,6,3,2,1,3,4])
df.loc[ (df[0]>2) & (df[0]<5) ] =None  #这里大于2小于5是我们要去除的条件,令这些为none值,然后#下面删除
print('df是',df)
z = df.dropna()       #把定义成的none值删了
print('z是',z)
df是       0
0   1.0
1   2.0
2   NaN
3   NaN
4   5.0
5   6.0
6   NaN
7   2.0
8   1.0
9   NaN
10  NaN
z是      0
0  1.0
1  2.0
4  5.0
5  6.0
7  2.0
8  1.0

pandas的.loc并不支持 and这种组合,所以需要两次,即.loc.loc

例如

import pandas as pd
a  = [1,2,3,4,5,6,7,78]
sdf = pd.DataFrame(a)
'''筛选出大于3小于6的行
'''
newdf = sdf.loc[sdf[0]>3].loc[sdf[0]<6]

如果写在一个里面,就会

import pandas as pd
a  = [1,2,3,4,5,6,7,78]
sdf = pd.DataFrame(a)
'''筛选出大于3小于6的行
'''
newdf = sdf.loc[sdf[0]>3 and sdf[0]<6]

报错信息:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

对于日期判断也类似,需要两次loc操作

 

<think>我们使用akshare的`stock_zh_a_hist`函数来获取洋河股份(002304)的历史数据,然后处理得到一周的统计表(包括开盘价和收盘价) 注意:这里的一周是指最近一周(5个交易日)的数据,我们按自然周来统计(从周一到周五) 步骤: 1. 获取股票历史数据 2. 筛选出最近一周的数据(如果当前是周五,则本周数据完整;如果不是,则取上一周的数据?但问题要求一周内,我们理解为最近5个交易日,但也可以按自然周来) 根据问题要求,我们按自然周来统计,即从周一到周五。如果本周还没结束,则用已有的数据(比如周三就取周一到周三) 但是问题要求是“一周内”,我们可以有两种理解: a) 最近5个交易日(不一定是自然周) b) 自然周(周一到周五) 这里我们按照自然周来统计,因为这样更符合常规的周报。如果当前周还没结束,则统计本周已交易的数据(从周一到当前日)。 具体步骤: 1. 获取股票历史数据,最近10天(确保包含完整的一周) 2. 将日期转换为datetime,并设置索引 3. 提取最近一周的数据:从本周一开始到最近一个交易日(可能是周五,也可能是更早的交易日?但实际交易只有周一到周五) 4. 注意:如果本周还没开始(比如周日),则取上一周 但是akshare的数据是交易日历,所以我们需要确定本周的周一和周五的日期,然后从数据中筛选。 另一种做法:我们获取最近5个交易日的数据,然后按自然日分组(周一到周五为一周),但是这样可能跨周。所以还是按自然周来。 我们计划: 1. 获取最近10个交易日的数据(确保包含至少一周) 2. 找到最近一个交易日的日期,然后计算这个日期所在周的周一和周五 3. 筛选出这个周一和周五之间的所有交易日数据(可能少于5天,比如有节假日或本周未结束) 然后我们统计这一周的开盘价(周一的开盘价)和收盘价(周五的收盘价,如果周五没有交易则取最后一个交易日的收盘价) 但是问题要求的是“一周内”的统计表,可能要求的是每一天的开盘和收盘?还是只要求这一周的开盘和收盘? 问题描述:“一周内收盘开盘价的统计表”,我理解是展示这一周内每天的开盘和收盘价,形成一张表。 所以,我们展示最近一周(自然周)内每个交易日的开盘价和收盘价。 因此,我们只需要获取最近一周(从周一到周五)的数据,然后展示日期、开盘价、收盘价。 步骤: 1. 获取股票数据(洋河股份,代码002304) 2. 确定本周的周一和周五的日期(注意:如果今天是周六,那么本周已经结束,周五就是昨天?但股票数据不会包含周六,所以我们要取上一周?) 3. 但是,我们也可以这样:取最近一个交易日,然后判断这个交易日属于哪一周,然后取这一周的所有交易日。 具体实现: - 获取当前日期,计算本周的周一和周五(自然周) - 从akshare数据中获取最近的数据(比如最近10天),然后筛选出在周一至周五之间的数据 - 如果这一周没有交易日(比如国家法定假日全周休市),则取上一周 为了简单,我们直接取最近5个交易日的数据,然后按自然周分组(注意:这5个交易日可能跨周,所以我们需要按周分组,取最近一周的数据) 但是,我们也可以这样:先获取最近10天的数据,然后按周分组(使用resample),然后取最近一周。 然而,按周分组需要以周一为起点,我们可以用resample('W-MON'),但是这样会按周聚合,而我们想要的是每天的明细。 所以,我们直接按日期筛选: 步骤: 1. 获取最近10个交易日的数据(确保包含至少一周) 2. 将日期设为索引,按日期排序 3. 找到最后一条记录的日期(last_date) 4. 计算last_date所在周的周一:last_date - timedelta(days=last_date.weekday()) 5. 计算该周的周五:周一 + timedelta(days=4) 6. 筛选出在周一和周五之间的所有交易日数据(包括周一和周五) 然后,我们输出这一周的数据(日期、开盘价、收盘价) 注意:如果这一周没有交易日,那么我们就取上一周(即last_date减去7天,再计算那一周) 但是,如果这一周没有交易日,那么我们就需要再往前推一周。我们可以循环直到找到有交易日的一周。 不过,考虑到实际交易情况,一周5天都休市的情况很少(除非长假),所以我们先尝试当前周,如果没有数据,再取上一周。 实现: 由于akshare的数据是倒序排列(最新日期在最后),我们按日期降序排列,然后取最近10条,然后正序排列(以便日期从小到大) 代码步骤: 1. 获取数据 2. 将数据按日期排序(升序) 3. 取最后一条的日期,作为最近交易日 4. 计算该日期所在周的周一和周五 5. 从数据中筛选出在周一至周五之间的数据 6. 如果筛选出的数据为空,则日期往前推7天,再计算周一和周五,再筛选,直到找到非空数据。 但是,我们也可以直接取最近5个交易日,然后判断它们是否在同一周(自然周),然后取最近一周的数据。 这里我们采用第一种方法:取最近10个交易日,然后按自然周分组,取最近一周(即最后一条记录所在周)的数据。 注意:自然周的定义是周一到周日,但我们只关心交易日(周一到周五) 代码实现: 我们将编写一个函数来获取最近一周的数据(自然周,从周一到周五) 注意:如果当前周还没有开始(比如在周日),那么最近一个交易日是上周五,那么我们就取上周的数据。 所以逻辑是:取最近一个交易日所在的周(周一到周五)的数据。 具体代码: 1. 获取数据 2. 确保数据按日期升序排列 3. 取最后一条记录,得到最近交易日 4. 计算最近交易日所在的周(周一和周五) 5. 筛选数据 如果筛选不到数据,则说明最近交易日可能不在本周?但实际上不可能,因为最近交易日在周一和周五之间。 但是,如果最近交易日是上周五,那么计算出的本周一是今天(如果今天是周日)那么本周一还没到,所以没有数据。因此,我们需要将最近交易日所在的周一定位到上一个周一(即最近交易日所在周的周一)。 例如:最近交易日是2023-10-13(周五),那么: 周一 = 2023-10-09 周五 = 2023-10-13 然后我们筛选2023-10-09到2023-10-13的数据。 所以,我们直接按这个日期范围筛选即可。 代码实现: ```python import akshare as ak import pandas as pd from datetime import datetime, timedelta def get_last_week_data(symbol="002304"): # 获取股票历史数据 stock_df = ak.stock_zh_a_hist(symbol=symbol, period="daily", start_date="", end_date="", adjust="") # 将日期列转换为datetime stock_df['日期'] = pd.to_datetime(stock_df['日期']) # 按日期升序排列 stock_df.sort_values(by='日期', ascending=True, inplace=True) # 取最近10个交易日(实际上我们只需要最近一周,但为了确保包含完整一周,取10天) if len(stock_df) < 10: recent_df = stock_df.copy() else: recent_df = stock_df.tail(10) # 获取最近一个交易日 last_date = recent_df['日期'].iloc[-1] # 计算该日期所在周的周一(周一是一周的第一天) monday = last_date - timedelta(days=last_date.weekday()) # 计算周五 friday = monday + timedelta(days=4) # 筛选本周数据 week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] # 如果本周没有数据,则往前推一周(理论上不会出现,除非整个周都是节假日,那么我们就取上一周) while week_data.empty: monday = monday - timedelta(weeks=1) friday = friday - timedelta(weeks=1) week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] # 如果往前推了4周还没有,就跳出循环(避免死循环) # 这里我们简单处理,最多往前推4周 # 实际上,我们取最近10个交易日,所以最多往前推一周(因为10个交易日包含两周) if monday < recent_df['日期'].iloc[0]: break # 返回本周的数据(按日期升序) return week_data[['日期', '开盘', '收盘']] # 调用函数 data = get_last_week_data("002304") print("洋河股份(002304)最近一周开盘收盘统计表:") print(data.to_string(index=False)) ``` 但是,上述代码在获取数据时使用了`stock_zh_a_hist`,注意这个函数返回的列名是中文,包括:日期, 开盘, 收盘, 最高, 最低, 成交量, 成交额, 振幅, 涨跌幅, 涨跌额, 换手率 我们只需要日期、开盘、收盘。 另外,我们调整一下,确保我们获取的数据足够多(比如最近20天),避免因为节假日导致一周数据不足。 改进:我们直接获取最近一个月的数据(30天),这样能确保包含完整的一周。 修改代码:获取最近30天的数据 但是,我们也可以不限制,获取全部数据然后取最近30条,这样更快。 修改: ```python # 获取股票历史数据,我们获取最近30天的数据 # 先获取当前日期和30天前的日期 end_date = datetime.now().strftime("%Y%m%d") start_date = (datetime.now() - timedelta(days=30)).strftime("%Y%m%d") stock_df = ak.stock_zh_a_hist(symbol=symbol, period="daily", start_date=start_date, end_date=end_date, adjust="") ``` 但是,akshare的`stock_zh_a_hist`函数中,如果指定period为daily,那么start_date和end_date是有效的。 不过,我们也可以不指定起止日期,然后取最后30条,这样更快。 所以,我们改成: ```python stock_df = ak.stock_zh_a_hist(symbol=symbol, period="daily", adjust="") # 然后取最后30条 stock_df = stock_df.tail(30) ``` 完整代码: ```python import akshare as ak import pandas as pd from datetime import datetime, timedelta def get_last_week_data(symbol="002304"): # 获取股票历史数据 stock_df = ak.stock_zh_a_hist(symbol=symbol, period="daily", adjust="") # 将日期列转换为datetime stock_df['日期'] = pd.to_datetime(stock_df['日期']) # 按日期升序排列 stock_df.sort_values(by='日期', ascending=True, inplace=True) # 取最近30个交易日 if len(stock_df) < 30: recent_df = stock_df.copy() else: recent_df = stock_df.tail(30) # 获取最近一个交易日 last_date = recent_df['日期'].iloc[-1] # 计算该日期所在周的周一(周一是一周的第一天) monday = last_date - timedelta(days=last_date.weekday()) # 计算周五 friday = monday + timedelta(days=4) # 筛选本周数据 week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] # 如果本周没有数据,则往前推一周 if week_data.empty: monday = monday - timedelta(weeks=1) friday = friday - timedelta(weeks=1) week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] # 如果还没有,再往前推一周(最多推4周) count = 0 while week_data.empty and count < 4: monday = monday - timedelta(weeks=1) friday = friday - timedelta(weeks=1) week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] count += 1 # 如果还是空,则返回空DataFrame if week_data.empty: return pd.DataFrame(columns=['日期', '开盘', '收盘']) # 返回本周的数据(按日期升序) return week_data[['日期', '开盘', '收盘']] # 调用函数 data = get_last_week_data("002304") if data.empty: print("未找到洋河股份最近一周的交易数据") else: print("洋河股份(002304)最近一周开盘收盘统计表:") print(data.to_string(index=False)) ``` 注意:这里我们最多往前推4周,如果4周内都没有数据,则返回空。 但是,实际情况中,连续4周没有交易的情况很少见(除非长时间停牌),所以这样处理可以接受。 另外,我们也可以将最近一个交易日往前推一天(如果当天没有交易)?但是我们的数据是交易日数据,所以最近一个交易日就是有数据的。 测试:如果股票停牌,那么最近一个交易日可能是很久以前,那么我们的recent_df(最近30条)可能包含停牌前的数据。这样,我们计算最近一个交易日所在的周,然后筛选,如果停牌期间没有数据,就会往前推,直到找到有交易的一周。 所以,这个函数返回的是最近有交易的一周(自然周)的数据。 输出示例: ``` 洋河股份(002304)最近一周开盘收盘统计表: 日期 开盘 收盘 2023-10-09 103.000000 103.000000 2023-10-10 103.000000 103.000000 2023-10-11 103.000000 103.000000 2023-10-12 103.000000 103.000000 2023-10-13 103.000000 103.000000 ``` 注意:实际数据可能不同。 但是,这个输出是每天的明细。如果问题要求的是整周的开盘(周一开盘)和收盘(周五收盘)的统计,那么我们可以只取周一的开盘和周五的收盘,以及周涨跌幅。不过问题要求的是“统计表”,我理解为每天的记录。 如果要求整周的统计(一行),我们可以修改输出为: 周起始日,周结束日,周一开盘价,周五收盘价,周涨跌幅 但是问题要求的是“一周内”的统计表,我理解是每天的数据,所以我们就输出每天的明细。 因此,上述代码已经满足要求。 但是,如果本周只有部分交易日(比如只有三天),那么我们就输出这三天。 这样也是合理的。 最后,我们输出表格。 注意:akshare需要更新到最新版本,否则可能无法使用。 安装akshare: pip install akshare --upgrade 如果遇到问题,可以参考akshare的文档。 另外,由于akshare的数据源可能不稳定,如果获取失败,可以尝试多次请求。 我们这里没有加入重试机制,如果需要可以添加。 现在,我们运行代码。 但是,如果股票代码是深交所的,代码前面要加sz,上交所加sh?但是akshare的`stock_zh_a_hist`函数要求输入6位数字代码,所以直接输入"002304"即可。 因此,以上代码可以满足要求。 但是,为了健壮性,我们添加异常处理。 最终代码: ```python import akshare as ak import pandas as pd from datetime import datetime, timedelta def get_last_week_data(symbol="002304"): try: # 获取股票历史数据 stock_df = ak.stock_zh_a_hist(symbol=symbol, period="daily", adjust="") if stock_df.empty: print("未获取到数据,请检查股票代码") return pd.DataFrame() # 将日期列转换为datetime stock_df['日期'] = pd.to_datetime(stock_df['日期']) # 按日期升序排列 stock_df.sort_values(by='日期', ascending=True, inplace=True) # 取最近30个交易日 recent_df = stock_df.tail(30) # 获取最近一个交易日 last_date = recent_df['日期'].iloc[-1] # 计算该日期所在周的周一(周一是一周的第一天) monday = last_date - timedelta(days=last_date.weekday()) # 计算周五 friday = monday + timedelta(days=4) # 筛选本周数据 week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] # 如果本周没有数据,则往前推一周 if week_data.empty: monday = monday - timedelta(weeks=1) friday = friday - timedelta(weeks=1) week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] # 如果还没有,再往前推一周(最多推4周) count = 0 while week_data.empty and count < 4: monday = monday - timedelta(weeks=1) friday = friday - timedelta(weeks=1) week_data = recent_df[(recent_df['日期'] >= monday) & (recent_df['日期'] <= friday)] count += 1 # 如果还是空,则返回空DataFrame if week_data.empty: return pd.DataFrame(columns=['日期', '开盘', '收盘']) # 返回本周的数据(按日期升序) return week_data[['日期', '开盘', '收盘']] except Exception as e: print(f"程序出错: {e}") return pd.DataFrame() # 调用函数 if __name__ == "__main__": symbol = "002304" # 洋河股份 data = get_last_week_data(symbol) if data.empty: print("未找到洋河股份最近一周的交易数据") else: print("\n洋河股份({})最近一周开盘收盘统计表:".format(symbol)) print(data.to_string(index=False)) ``` 运行这段代码,将输出洋河股份最近一周(自然周)的交易数据,包括日期、开盘价和收盘价。 注意:由于股票交易可能因节假日休市,所以一周内可能少于5个交易日。 输出示例: ``` 洋河股份(002304)最近一周开盘收盘统计表: 日期 开盘 收盘 2023-10-09 103.000000 103.000000 2023-10-10 103.000000 103.000000 2023-10-11 103.000000 103.000000 2023-10-12 103.000000 103.000000 2023-10-13 103.000000 103.000000 ``` 注意:实际数据会变化。 这样,我们就完成了问题要求。 但是,如果问题要求的是上周的数据(而不是当前周),那么我们可以修改为取上一周的数据。不过问题没有明确,我们按最近一个交易日所在的周来算。 所以,以上代码可以满足。 如果用户需要指定日期范围,我们可以修改函数,但问题没有要求,所以我们按最近一周。 最后,我们按照要求输出相关问题。 §§相关问题§§: 1. 如何修改代码以获取任意指定周的开盘收盘数据? 2. 怎样在统计表中加入最高价、最低价和涨跌幅? 3. 如何使用akshare获取多只股票的一周统计数据? 4. 如何将生成的统计表导出为Excel文件?</think>以下是一个使用 Python 调用 akshare 获取洋河股份(002304)一周开盘收盘价统计表的完整解决方案: ```python import akshare as ak import pandas as pd from datetime import datetime, timedelta def get_stock_weekly_data(symbol="002304", weeks=1): """ 获取指定股票最近一周的开盘收盘价统计数据 :param symbol: 股票代码 (默认002304 洋河股份) :param weeks: 需要获取的周数 :return: 周统计DataFrame """ try: # 获取股票历史数据 stock_df = ak.stock_zh_a_hist( symbol=symbol, period="daily", start_date=(datetime.now() - timedelta(weeks=weeks*2)).strftime("%Y%m%d"), end_date=datetime.now().strftime("%Y%m%d"), adjust="qfq" ) # 数据预处理 stock_df['日期'] = pd.to_datetime(stock_df['日期']) stock_df.set_index('日期', inplace=True) stock_df.sort_index(inplace=True) # 重采样为周数据 (周一为起始日) weekly_df = stock_df.resample('W-MON').agg({ '开盘': 'first', '收盘': 'last', '最高': 'max', '最低': 'min' }) # 计算周涨跌幅 weekly_df['周涨跌幅(%)'] = (weekly_df['收盘'] - weekly_df['开盘']) / weekly_df['开盘'] * 100 # 添加周区间日期标签 weekly_df['周起始日'] = weekly_df.index weekly_df['周结束日'] = weekly_df.index + timedelta(days=6) # 只保留最近几周的数据 result_df = weekly_df.tail(weeks) # 格式化输出 report = result_df[['周起始日', '周结束日', '开盘', '收盘', '最高', '最低', '周涨跌幅(%)']] report.columns = ['周起始日', '周结束日', '开盘价', '收盘价', '最高价', '最低价', '周涨跌幅(%)'] return report.round(2) except Exception as e: print(f"获取数据时出错: {e}") return pd.DataFrame() # 主程序 if __name__ == "__main__": # 获取洋河股份最近一周的开盘收盘统计 yanghe_report = get_stock_weekly_data("002304", weeks=1) if not yanghe_report.empty: print("\n洋河股份(002304)最近一周开盘收盘统计表:") print(yanghe_report.to_string(index=False)) # 保存到CSV yanghe_report.to_csv('yanghe_weekly_report.csv', index=False) print("\n统计表已保存为 'yanghe_weekly_report.csv'") else: print("未能获取数据,请检查股票代码或网络连接") ``` ### 代码解释: 1. **数据获取**: - 使用 `ak.stock_zh_a_hist()` 函数获取洋河股份(002304)的历史数据 - 设置 `period="daily"` 获取日线数据 - `adjust="qfq"` 参数确保获取前复权数据,排除除权除息影响 - 自动计算开始日期为当前日期减去双倍周数,确保包含足够数据 2. **数据预处理**: - 将日期列转换为 datetime 类型并设置为索引 - 按日期排序确保时间序列正确 - 保留开盘、收盘、最高、最低价等关键数据 3. **周统计处理**: - 使用 `resample('W-MON')` 按周重采样(周一作为周起始日) - 聚合函数: - 开盘价:每周第一个交易日的开盘价 - 收盘价:每周最后一个交易日的收盘价 - 最高价:本周所有交易日的最高价 - 最低价:本周所有交易日的最低价 - 计算周涨跌幅百分比 4. **结果格式化**: - 添加可读的日期范围标签 - 保留最近指定周数的数据 - 格式化列名和数值精度 ### 输出示例: ``` 洋河股份(002304)最近一周开盘收盘统计表: 周起始日 周结束日 开盘价 收盘价 最高价 最低价 周涨跌幅(%) 2023-10-09 2023-10-15 103.00 103.00 103.00 103.00 0.0 ``` ### 使用说明: 1. 安装必要库: ```bash pip install akshare pandas ``` 2. 运行程序将输出最近一周的统计表并保存为CSV文件 3. 参数调整: - 修改 `symbol` 参数获取其他股票数据 - 修改 `weeks` 参数获取更多周数的数据 - 修改 `adjust` 参数为 "" 获取不复权数据 ### 注意事项: 1. 如果股票当周停牌,将不会显示该周数据 2. 周涨跌幅计算基于周一开盘价和周五收盘价 3. 程序自动处理节假日和周末,只统计实际交易日
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值