You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas groupby函数失效,无法计算河道流量日均数据

问题描述

我用Python从政府网站抓取某河道15分钟间隔的流量(cfs)数据,想计算4天内的日均流量。目前用BeautifulSoup爬取数据转存CSV后导入Pandas DataFrame,已完成数据清洗并将date列转为datetime类型,但调用groupby('date').mean()后新DataFrame没有变化,没法得到日均数据,请问问题出在哪?是否需要修改日期列?

相关代码

import requests
from bs4 import BeautifulSoup
import csv
import io
import pandas as pd

url = "https://www.usbr.gov/pn-bin/instant.pl?parameter=CHRO%20q&syer=2023&smnth=3&sdy=25&eyer=2023&emnth=4&edy=4&format=2"

response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
data = soup.findAll('pre')[1]

stringdata = str(data) # 转换为字符串
stringdata = stringdata[53:] # 去掉顶部无关文本
input_data = io.StringIO(stringdata)  # 转为可读取的字符串流

# 写入CSV文件
with open ('cherryCreek.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    reader = csv.reader(input_data)
    for row in reader:
        writer.writerow(row)

df = pd.read_csv('cherryCreek.csv', names=['date','cfs'])
df = df.iloc[:-2] # 截断最后两行无关文本
df['date'] = pd.to_datetime(df['date'], utc=True)

df_avg = df.groupby('date').mean()
df_avg.head()

问题原因

你现在用date列做分组,但date列是精确到分钟的完整时间戳(比如2023-03-25 00:00:00+00:00),每个时间戳都是唯一的,分组后每个组里只有一条数据,计算均值自然和原数据完全一致,根本达不到按天聚合的目的。

解决方法

方法1:提取纯日期字段分组

直接从时间戳里提取年-月-日的日期部分,生成新列后分组:

# 提取日期部分,生成仅含年月日的新列
df['date_only'] = df['date'].dt.date
# 按纯日期分组计算日均流量
df_avg = df.groupby('date_only')['cfs'].mean().reset_index()

方法2:用resample做时间序列聚合

Pandas的resample是专门处理时间序列频率转换的工具,更适合这种场景:

# 先将date列设为DataFrame的索引
df = df.set_index('date')
# 按天('D')聚合计算均值,reset_index()把索引转回列
df_avg = df.resample('D')['cfs'].mean().reset_index()

这里的'D'代表天级频率,其他常用频率参数还有'H'(小时)、'W'(周)等。

方法3:截断时间戳到当天起始点

把时间戳向下截断到当天的0点,再按截断后的时间分组:

# 截断时间到天的起始时刻
df['date_floor'] = df['date'].dt.floor('D')
# 按截断后的时间分组计算均值
df_avg = df.groupby('date_floor')['cfs'].mean().reset_index()

内容的提问来源于stack exchange,提问作者dls2235

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:25:42