一个简单的小项目,青藏高原上的站点将近50年的降雨统计。
使用pandas来进行数据处理和分析,原数据书储存在excel表格中的。700多各站点,从1951年到2005年的每年每个月的降雨量统计。为此,需要计算出每个站点,每年的年总降雨量,年均降雨量,月均降雨量(比如一月份,从1951到2005年的平均降雨量)。
import pandas as pd
import numpy as np
import csv
##读取文件
df = pd.read_excel('1951_2005.xlsx')
# df_new = df[df['台站']==50136]
# df_new = df_new[df_new['年']==1957]
# print(df_new)
##统计台站编号
num_tz = df['台站'] ###统计所有的台站
num_tz = set(np.array(num_tz)) ###将台站编号放入set(),并去重
num_tz = sorted(num_tz)
def rain_data():
for i_tz in num_tz:
df_1 = df[df['台站'] == i_tz]
for j_year in range(1951, 2006):
info = {}
df_2 = df_1[df_1['年'] == j_year]
rain_year_sum = df_2['降水量'].sum() ##各站点年总降水量
# rain_month_avg = df_2['降水量'].mean() ##各站点每一年的逐月平均降水量
info['台站'] = i_tz
info['year'] = j_year
info['总降雨量'] = rain_year_sum
# info['月均降雨'] = round(rain_month_avg, 2)
data.append(info)
###年均降雨量
info2 = {}
rain_tz_sum = df_1['降水量'].sum() ##一个台站所有的降水量
num_year = df_1['年']
num_year = len(set(np.array(num_year)))
rain_year_avg = float(rain_tz_sum) / float(num_year) ##一个台站的平均每年降水量
info2['台站'] = i_tz
info2['年均降雨量'] = round(rain_year_avg, 2)
data2.append(info2)
###多年逐月平均降雨量
for k_month in range(1, 13):
info3 = {}
df_3 = df_1[df_1['月'] == k_month]
rain_month_avg = df_3['降水量'].mean() ##某一个站点某一个月的平均降水量
rain_month_avg = round(rain_month_avg,2)
info3['台站'] = i_tz
info3['month'] = k_month
info3['月均降雨量'] = rain_month_avg
data3.append(info3)
return data,data2,data3
if __name__=='__main__':
data = []
data2 = []
data3 = []
data,data2,data3 = rain_data()
# print(data,data2)
header = ['台站', 'year', '总降雨量']
# print(data)
with open('rain_data1.csv', 'w') as dstfile: # 写入方式选择a,否则有空行
writer = csv.DictWriter(dstfile, fieldnames=header)
writer.writeheader() # 写入表头
writer.writerows(data) # 批量写入
dstfile.close()
header2 = ['台站', '年均降雨量']
with open('rain_data2.csv', 'w') as dstfile2: # 写入方式选择a,否则有空行
writer2 = csv.DictWriter(dstfile2, fieldnames=header2)
writer2.writeheader() # 写入表头
writer2.writerows(data2) # 批量写入
dstfile2.close()
header3 = ['台站','month','月均降雨量']
with open('rain_data3.csv', 'w') as dstfile3: # 写入方式选择a,否则有空行
writer3 = csv.DictWriter(dstfile3, fieldnames=header3)
writer3.writeheader() # 写入表头
writer3.writerows(data3) # 批量写入
dstfile3.close()
编程过程中遇到的问题以及解决方法:
1、pandas的使用,其中用到的函数都可以在 Pandas速查手册中文版中找到。
总结下:
pandas中主要有两种数据结构:DataFrame和Series
DataFrame:
Series:是dataframe其中一列
因此可以直接从excel之类的文件导入,数据类型可以是任意的,厉害了~
当然还可以自己导出dataframe:
1、通过传递一个numpy array,时间索引以及列标签来创建一个DataFrame。上面的代码中data就是这样的一个dict,然后将其以csv的形式导出。
2、通过传递一个能够被转换成类似序列结构的字典对象来创建一个DataFrame
3、1、可以通过传递一个list对象来创建一个Series,pandas会默认创建整型索引
2、set()函数:可以用来去重,但得到的结果是顺序会被打乱。这里因为本身数据是升序,所以直接使用sorted()
注意sorted()和sort()使用的区别:Python 列表排序方法reverse、sort、sorted详解
a = [1,5,3,6,4,2,5,4,1,5,6,9]
b = list(set(a))
print('sort()function:', b.sort())
print('sorted() function:',sorted(b))
运行结果:
sort()function: None ##无返回值
sorted() function: [1, 2, 3, 4, 5, 6, 9]
sort()是可变对象(字典、列表)的方法,无参数,无返回值,sort()会改变可变对象,因此无需返回值。sort()方法是可变对象独有的方法或者属性,而作为不可变对象如元组、字符串是不具有这些方法的,如果调用将会返回一个异常。
sorted()是python的内置函数,并不是可变对象(列表、字典)的特有方法,sorted()函数需要一个参数(参数可以是列表、字典、元组、字符串),无论传递什么参数,都将返回一个以列表为容器的返回值,如果是字典将返回键的列表。
a = [1,5,3,6,4,2,5,4,1,5,6,9]
b = list(set(a))
b.sort()
print(b)
运行结果:[1, 2, 3, 4, 5, 6, 9]
3、关于从excel文件中数据的筛选:用Pandas完成Excel中常见的任务
关于数据导出成scv文件:python列表、字典与csv
4、两个循环嵌套,输出的结果始终是最后一组数据?
info = {}
data = []
for i in range(3):
for j in range(3):
info['台站'] = i
info['year'] = j
info['总降雨量'] = i+1
info['月均降雨'] = j+2
data.append(info)
print(data)
运行结果:
[{'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}]
###修正后的
data = []
for i in range(3):
for j in range(3):
info = {}
info['台站'] = i
info['year'] = j
info['总降雨量'] = i+1
info['月均降雨'] = j+2
data.append(info)
print(data)
修正后的结果:
[{'台站': 0, 'year': 0, '总降雨量': 1, '月均降雨': 2}, {'台站': 0, 'year': 1, '总降雨量': 1, '月均降雨': 3}, {'台站': 0, 'year': 2, '总降雨量': 1, '月均降雨': 4}, {'台站': 1, 'year': 0, '总降雨量': 2, '月均降雨': 2}, {'台站': 1, 'year': 1, '总降雨量': 2, '月均降雨': 3}, {'台站': 1, 'year': 2, '总降雨量': 2, '月均降雨': 4}, {'台站': 2, 'year': 0, '总降雨量': 3, '月均降雨': 2}, {'台站': 2, 'year': 1, '总降雨量': 3, '月均降雨': 3}, {'台站': 2, 'year': 2, '总降雨量': 3, '月均降雨': 4}]
区别在于:
info在外面的时候 你append的都是同一个对象, 修改info会修改data里面的每个info值。
就是之前添加在list里面的是info,放在堆里面的一个名字,info对应的栈内存的值变了。