使用python和pandas按季节和年份将csv中的数据分组

使用python和pandas按季节和年份将csv中的数据分组,python,csv,pandas,mean,Python,Csv,Pandas,Mean,这是一个扩展 我想使用Pandas和Python迭代我的.csv文件,并按季节(和年份)对数据进行分组,计算一年中每个季节的平均值。目前,季度脚本是1月至3月、4月至6月等。我希望季节与月份相关 -11:“冬天”,12:“冬天”,1:“冬天”,2:“春天”,3:“春天”,4:“春天”,5:“夏天”,6:“夏天”,7:“夏天”\ 8:‘秋天’,9:‘秋天’,10:‘秋天’ 我有以下数据: Date,HAD 01/01/1951,1 02/01/1951,-0.13161201 03/01/1951

这是一个扩展

我想使用Pandas和Python迭代我的.csv文件,并按季节(和年份)对数据进行分组,计算一年中每个季节的平均值。目前,季度脚本是1月至3月、4月至6月等。我希望季节与月份相关

-11:“冬天”,12:“冬天”,1:“冬天”,2:“春天”,3:“春天”,4:“春天”,5:“夏天”,6:“夏天”,7:“夏天”\
8:‘秋天’,9:‘秋天’,10:‘秋天’

我有以下数据:

Date,HAD
01/01/1951,1
02/01/1951,-0.13161201
03/01/1951,-0.271796132
04/01/1951,-0.258977158
05/01/1951,-0.198823057
06/01/1951,0.167794502
07/01/1951,0.046093808
08/01/1951,-0.122396694
09/01/1951,-0.121824587
10/01/1951,-0.013002463

一直到

20/12/2098,62.817
21/12/2098,59.998
22/12/2098,50.871
23/12/2098,88.405
24/12/2098,81.154
25/12/2098,83.617
26/12/2098,120.675
27/12/2098,273.795
28/12/2098,316.324
29/12/2098,260.951
30/12/2098,198.505
31/12/2098,150.755
这是前一个问题中的代码,它是有效的

import pandas as pd
import os
import re

lookup = {
    11: 'Winter',
    12: 'Winter',
    1: 'Winter',
    2: 'Spring',
    3: 'Spring',
    4: 'Spring',
    5: 'Summer',
    6: 'Summer',
    7: 'Summer',
    8: 'Autumn',
    9: 'Autumn',
    10: 'Autumn'
}

os.chdir('C:/Users/n-jones/testdir/output/')

for fname in os.listdir('.'):
    if re.match(".*csv$", fname):
        data = pd.read_csv(fname, parse_dates=[0], dayfirst=True)
        data['Season'] = data['Date'].apply(lambda x: lookup[x.month])
        data['count'] = 1
        data = data.groupby(['Season'])['HAD', 'count'].sum()
        data['mean'] = data['HAD'] / data['count']
        data.to_csv('C:/Users/n-jones/testdir/season/' + fname)
我希望我的输出csv文件为:

Autumn 1951, Mean, Winter 1951/52, Mean, Spring 1952, Mean, Summer 1952, Mean,
Autumn 1952, Mean, Winter 1952/53, Mean, Spring 1953, Mean, Summer 1953, Mean,
等等

我希望这有点道理


提前谢谢你

这是一个完美的例子,说明你最好的朋友是谁

请原谅我没有扩展你的答案,但我对熊猫不太熟悉,所以我选择使用csv模块

通过编写两种数据分组方法(
get_seasure
get_year
),只需迭代组,然后将数据写入新的csv文件

import csv
from datetime import datetime
from itertools import groupby

LOOKUP_SEASON = {
    11: 'Winter',
    12: 'Winter',
    1: 'Winter',
    2: 'Spring',
    3: 'Spring',
    4: 'Spring',
    5: 'Summer',
    6: 'Summer',
    7: 'Summer',
    8: 'Autumn',
    9: 'Autumn',
    10: 'Autumn'
}


def get_season(row):
    date = datetime.strptime(row[0], '%d/%m/%Y')
    season = LOOKUP_SEASON[date.month]
    if season == 'Winter':
        if date.month == 1:
            last_year, next_year = date.year - 1, date.year
        else:
            last_year, next_year = date.year, date.year + 1
        return '{} {}/{}'.format(season, last_year, next_year)
    else:
        return '{} {}'.format(season, date.year)


def get_year(row):
    date = datetime.strptime(row[0], '%d/%m/%Y')
    if date.month < 8:
        return date.year - 1
    else:
        return date.year


with open('NJDATA.csv') as data_file, open('outfile.csv', 'wb') as out_file:
    headers = next(data_file)
    reader = csv.reader(data_file)
    writer = csv.writer(out_file)

    # Loop over groups distinguished by the "year" from Autumn->Summer,
    # defined by the `get_year` function
    for year, seasons in groupby(reader, get_year):
        mean_data = []
        # Loop over the data in the current year, grouped by season, defined
        # by the get_season method. Since the required "season string"
        # (e.g Autumn 1952) can be used as an identifier for the seasons,
        # the `get_season` method returns the specific string which is used
        # in the output, so you don't have to compile that one more time
        # inside the for loops
        for season_str, iter_data in groupby(seasons, get_season):
            data = list(iter_data)
            mean = sum([float(row[1]) for row in data]) / len(data)
            # Use the next line instead if you want to control the precision
            #mean = '{:.3f}'.format(sum([float(row[1]) for row in data]) / len(data))
            mean_data.extend([season_str, mean])
        writer.writerow(mean_data)
第一个
groupby
调用根据您的年份定义(在
get\u year
中定义)对数据进行分组,给出以下数据组:

# get_year returns 1950
01/01/1951,1
...
05/06/1951,-0.198823057

# get_year returns 1951 
06/08/1951,0.167794502
...
09/02/1952,-0.121824587
下一个
groupby
方法根据季节(在
get\u seasure
中定义)对上述各组进行分组。让我们考虑第一组:

# get_season returns 'Winter 1950/1951'
01/01/1951,1
02/01/1951,-0.13161201

# get_season returns 'Spring 1951'
01/04/1951,1
02/04/1951,-0.13161201
03/04/1951,-0.271796132

# get_season returns 'Summer 1951'
04/06/1951,-0.258977158
05/06/1951,-0.198823057

这是一个完美的例子,说明你最好的朋友是谁

请原谅我没有扩展你的答案,但我对熊猫不太熟悉,所以我选择使用csv模块

通过编写两种数据分组方法(
get_seasure
get_year
),只需迭代组,然后将数据写入新的csv文件

import csv
from datetime import datetime
from itertools import groupby

LOOKUP_SEASON = {
    11: 'Winter',
    12: 'Winter',
    1: 'Winter',
    2: 'Spring',
    3: 'Spring',
    4: 'Spring',
    5: 'Summer',
    6: 'Summer',
    7: 'Summer',
    8: 'Autumn',
    9: 'Autumn',
    10: 'Autumn'
}


def get_season(row):
    date = datetime.strptime(row[0], '%d/%m/%Y')
    season = LOOKUP_SEASON[date.month]
    if season == 'Winter':
        if date.month == 1:
            last_year, next_year = date.year - 1, date.year
        else:
            last_year, next_year = date.year, date.year + 1
        return '{} {}/{}'.format(season, last_year, next_year)
    else:
        return '{} {}'.format(season, date.year)


def get_year(row):
    date = datetime.strptime(row[0], '%d/%m/%Y')
    if date.month < 8:
        return date.year - 1
    else:
        return date.year


with open('NJDATA.csv') as data_file, open('outfile.csv', 'wb') as out_file:
    headers = next(data_file)
    reader = csv.reader(data_file)
    writer = csv.writer(out_file)

    # Loop over groups distinguished by the "year" from Autumn->Summer,
    # defined by the `get_year` function
    for year, seasons in groupby(reader, get_year):
        mean_data = []
        # Loop over the data in the current year, grouped by season, defined
        # by the get_season method. Since the required "season string"
        # (e.g Autumn 1952) can be used as an identifier for the seasons,
        # the `get_season` method returns the specific string which is used
        # in the output, so you don't have to compile that one more time
        # inside the for loops
        for season_str, iter_data in groupby(seasons, get_season):
            data = list(iter_data)
            mean = sum([float(row[1]) for row in data]) / len(data)
            # Use the next line instead if you want to control the precision
            #mean = '{:.3f}'.format(sum([float(row[1]) for row in data]) / len(data))
            mean_data.extend([season_str, mean])
        writer.writerow(mean_data)
第一个
groupby
调用根据您的年份定义(在
get\u year
中定义)对数据进行分组,给出以下数据组:

# get_year returns 1950
01/01/1951,1
...
05/06/1951,-0.198823057

# get_year returns 1951 
06/08/1951,0.167794502
...
09/02/1952,-0.121824587
下一个
groupby
方法根据季节(在
get\u seasure
中定义)对上述各组进行分组。让我们考虑第一组:

# get_season returns 'Winter 1950/1951'
01/01/1951,1
02/01/1951,-0.13161201

# get_season returns 'Spring 1951'
01/04/1951,1
02/04/1951,-0.13161201
03/04/1951,-0.271796132

# get_season returns 'Summer 1951'
04/06/1951,-0.258977158
05/06/1951,-0.198823057

以下是一个简单的解决方案:

import pandas as pd

def year_and_season(x):
    season = lookup[x.month]
    year = x.year
    if x.month == 12:
        year += 1
    return (year, season)

data = pd.read_csv('example.csv', index_col=0, parse_dates=[0], dayfirst=True)
yearsAndSeason = data.groupby(year_and_season).mean()
yearsAndSeason.to_csv('results.csv')
请注意,reading设置为日期时的索引列,因此我们可以在
groupBy
函数中直接访问其字段。在那里,我们返回一个元组,包含年份和季节。您可以直接调用
mean
函数,而不是
sum

results.csv
看起来与您期望的不完全一样,因为键以元组形式打印,但您可能可以计算出该部分。这就是我的感觉

$ cat results.csv
,Mean
"(1951, 'Winter')",0.009545620900000005
"(2099, 'Winter')",145.65558333333334

以下是一个简单的解决方案:

import pandas as pd

def year_and_season(x):
    season = lookup[x.month]
    year = x.year
    if x.month == 12:
        year += 1
    return (year, season)

data = pd.read_csv('example.csv', index_col=0, parse_dates=[0], dayfirst=True)
yearsAndSeason = data.groupby(year_and_season).mean()
yearsAndSeason.to_csv('results.csv')
请注意,reading设置为日期时的索引列,因此我们可以在
groupBy
函数中直接访问其字段。在那里,我们返回一个元组,包含年份和季节。您可以直接调用
mean
函数,而不是
sum

results.csv
看起来与您期望的不完全一样,因为键以元组形式打印,但您可能可以计算出该部分。这就是我的感觉

$ cat results.csv
,Mean
"(1951, 'Winter')",0.009545620900000005
"(2099, 'Winter')",145.65558333333334

我遇到了同样的问题,发现重采样方法可以通过使用参数3M(3个月)来实现这一点

我发现这一点要感谢这个网站,他给出了一个与这个问题相关的例子

如果您有一个索引为datetime对象的数据帧,那么您需要做的就是要求在3个月的基础上重新采样

In [108]:
data.head()
Out[108]:
         Sample Measurement
              mean
Date Local  
2006-01-01  50.820833
2006-01-02  41.900000
2006-01-03  45.870833
2006-01-04  50.850000
2006-01-05  37.116667

In[109]:
#88 in order to beginn the resampling in march
wm = data[88:].resample('3M', closed='left')
wm.head()
out[109]:
         Sample Measurement
              mean
Date Local  
2006-05-31  7.153622
2006-08-31  5.883025
2006-11-30  11.619724
2007-02-28  21.105789
2007-05-31  8.105313

这是我的数据集上的每日值,我确实丢失了前三个月的数据,但我认为这是一种处理季节的非常简单的方法。我遇到了同样的问题,发现重采样方法可以使用参数3M(3个月)来实现这一点

我发现这一点要感谢这个网站,他给出了一个与这个问题相关的例子

如果您有一个索引为datetime对象的数据帧,那么您需要做的就是要求在3个月的基础上重新采样

In [108]:
data.head()
Out[108]:
         Sample Measurement
              mean
Date Local  
2006-01-01  50.820833
2006-01-02  41.900000
2006-01-03  45.870833
2006-01-04  50.850000
2006-01-05  37.116667

In[109]:
#88 in order to beginn the resampling in march
wm = data[88:].resample('3M', closed='left')
wm.head()
out[109]:
         Sample Measurement
              mean
Date Local  
2006-05-31  7.153622
2006-08-31  5.883025
2006-11-30  11.619724
2007-02-28  21.105789
2007-05-31  8.105313

这是我的每日值数据集,我确实丢失了前三个月的数据,但我认为这是一种非常简单的处理季节的方法

你能上传一个更大的数据样本吗(例如使用pastebin或类似工具)?到csv文件的dropbox链接-可以吗?请上传更大的数据样本(例如使用pastebin或类似工具)?到csv文件的dropbox链接-这可以吗?谢谢steinar,我现在会查看一下。我上传了一个csv示例供您查看。谢谢Stenina,我想知道您是否可以澄清或评论您的代码?对于年份,groupby中的季节(reader,get_year):mean_data=[]对于季节,groupby中的iter_数据(seasons,get_season):data=list(iter_数据)mean=sum([float(row[1])对于数据中的row])/len mean(data)mean_数据。extend([season_str,mean])另一个额外的问题是我有13列数据,例如Date Had1有2有3。。。这容易合并吗?非常感谢steinar,我已经研究出如何添加额外的数据列。这太棒了:)嗨,斯泰纳,我不知道你不能接受两个答案——一个简单的问题。我在查找时犯了一个错误,应该是查找季节={12:'冬天',1:'冬天',2:'冬天',3:'春天',4:'春天',5:'春天',6:'夏天',7:'夏天',8:'夏天',9:'秋天',10:'秋天',11:'秋天',}我把代码弄乱了,所以我想我已经让它工作了,但它会生成两次冬季结果。谢谢Nickthanks steinar我现在就来看看。我上传了一个csv示例供您查看。谢谢Stenina,我想知道您是否可以澄清或评论您的代码?对于年,groupby中的季节(读者,获取年):s的平均数据=[]