pandas模块的使用(三)

为DataFrame添加一列数据:

In [16]: x = pd.DataFrame(np.arange(12).reshape(3,4),columns=list("QWER"))

In [17]: x
Out[17]: 
   Q  W   E   R
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

In [18]: x["O"]= pd.DataFrame(np.arange(3).reshape(3,1))

In [19]: x
Out[19]: 
   Q  W   E   R  O
0  0  1   2   3  0
1  4  5   6   7  1
2  8  9  10  11  2
  • 现在我们有2015到2017年25万条911的紧急电话的数据,请统计出出这些数据中不同类型的紧急情况的次数,如果我们还想统计出不同月份不同类型紧急电话的次数的变化情况,应该怎么做呢?

  • 数据来源:https://www.kaggle.com/mchirico/montcoalert/data

数据格式

lat				lng										desc										zip				 title			timeStamp			twp			addr	  			   e
40.2978759	-75.5812935	REINDEER CT & DEAD END;  NEW HANOVER; Station 332; 2015-12-10 @ 17:10:52;	19525	EMS: BACK PAINS/INJURY	2015/12/10 17:10	NEW HANOVER	REINDEER CT & DEAD END	1
40.2580614	-75.2646799	BRIAR PATH & WHITEMARSH LN;  HATFIELD TOWNSHIP; Station 345; 2015-12-10 @ 17:29:21;	19446	EMS: DIABETIC EMERGENCY	2015/12/10 17:29	HATFIELD TOWNSHIP	BRIAR PATH & WHITEMARSH LN	1

代码:

import pandas as pd
import numpy as np

# 准备数据
df = pd.read_csv("./911.csv")

# print(df["title"].head(5))
# print(df.info())

# 提取数据
temp_list = df["title"].str.split(": ").tolist()
# 不同的紧急情况
cate_list = list(set([i[0] for i in temp_list]))
# print(cate_list)

# 构造全为0的数组
zeros_df = pd.DataFrame(np.zeros((df.shape[0],len(cate_list))),columns=cate_list)

# 赋值
for cate in cate_list:
    # 利用布尔索引实现一次对一列进行赋值
    zeros_df[cate][df["title"].str.contains(cate)] = 1
    
# print(zeros_df)

# 求和
print(zeros_df.sum(axis=0))

----------------------------------

import pandas as pd
import numpy as np

# 准备数据
df = pd.read_csv("./911.csv")

# print(df["title"].head(5))
# print(df.info())


# 提取数据
temp_list = df["title"].str.split(": ").tolist()
# 不同的紧急情况
cate_list = [i[0] for i in temp_list]


# 添加一列数据
df["cate"] = pd.DataFrame(np.array(cate_list).reshape((df.shape[0],1)))

# 分组统计
print(df.groupby(by="cate").count()["title"])

pandas中的时间序列:

生成一段时间范围:


pd.date_range(start=None, end=None, periods=None, freq='D')

start和end以及freq配合能够生成start和end范围内以频率freq的一组时间索引
start和periods以及freq配合能够生成从start开始的频率为freq的periods个时间索引

In [2]: pd.date_range(start="20191010",end="20201122")
Out[2]: 
DatetimeIndex(['2019-10-10', '2019-10-11', '2019-10-12', '2019-10-13',
               '2019-10-14', '2019-10-15', '2019-10-16', '2019-10-17',
               '2019-10-18', '2019-10-19',
               ...
               '2020-11-13', '2020-11-14', '2020-11-15', '2020-11-16',
               '2020-11-17', '2020-11-18', '2020-11-19', '2020-11-20',
               '2020-11-21', '2020-11-22'],
              dtype='datetime64[ns]', length=410, freq='D')


In [3]: pd.date_range(start="20191010",end="20201122",freq="BM")
Out[3]: 
DatetimeIndex(['2019-10-31', '2019-11-29', '2019-12-31', '2020-01-31',
               '2020-02-28', '2020-03-31', '2020-04-30', '2020-05-29',
               '2020-06-30', '2020-07-31', '2020-08-31', '2020-09-30',
               '2020-10-30'],
              dtype='datetime64[ns]', freq='BM')

In [4]: pd.date_range(start="20191010",periods=10,freq="WOM-3FRI")
Out[4]: 
DatetimeIndex(['2019-10-18', '2019-11-15', '2019-12-20', '2020-01-17',
               '2020-02-21', '2020-03-20', '2020-04-17', '2020-05-15',
               '2020-06-19', '2020-07-17'],
              dtype='datetime64[ns]', freq='WOM-3FRI')

关于频率的更多缩写:

别名           偏移量类型             说明
D                Day              每日历日              
B             BusinessDay         每工作日
H                Hour             每小时
T或min          Minute            每分
S               Second            每秒
L或ms            Milli            每毫秒(即每千分之一秒)
U                Micro            每微秒(即每百万分之一秒)
M               MonthEnd          每月最后一个日历日
BM          BusinessMonthEnd      每月最后一个工作日
MS           MonthBegin           每月第一个日历日
BMS        BusinessMonthBegin     每月第一个工作日

在DataFrame中使用时间序列:

index=pd.date_range("20170101",periods=10)
df = pd.DataFrame(np.random.rand(10),index=index)


回到最开始的911数据的案例中,我们可以使用pandas提供的方法把时间字符串转化为时间序列

df["timeStamp"] = pd.to_datetime(df["timeStamp"],format="")

format参数大部分情况下可以不用写,但是对于pandas无法格式化的时间字符串,我们可以使用该参数,比如包含中文


那么问题来了:
我们现在要统计每个月或者每个季度的次数怎么办呢?

pandas重采样:

重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,
低频率转化为高频率为升采样

pandas提供了一个resample的方法来帮助我们实现频率转化

np.random.uniform(10,50,(100,1))的作用:生成100行1列的10到50之间的随机数二维数组

In [3]: t = pd.DataFrame(np.random.uniform(10,50,(100,1)),index=pd.date_range("20210912",periods=100))

In [4]: t
Out[4]: 
                    0
2021-09-12  48.035949
2021-09-13  10.695941
2021-09-14  40.903627
2021-09-15  19.935708
2021-09-16  35.640888
...               ...
2021-12-16  40.102581
2021-12-17  24.833710
2021-12-18  10.483476
2021-12-19  29.515657
2021-12-20  39.668012


In [6]: t.resample("M").mean()  # mean取降采样前到降采样后,缺失数据的均值,一般此mean为固定格式
Out[6]: 
                    0
2021-09-30  33.396144
2021-10-31  30.037768
2021-11-30  28.952921
2021-12-31  26.474234

In [7]: t.resample("10D").count()
Out[7]: 
             0
2021-09-12  10
2021-09-22  10
2021-10-02  10
2021-10-12  10
2021-10-22  10
2021-11-01  10
2021-11-11  10
2021-11-21  10
2021-12-01  10
2021-12-11  10

In [8]: t.resample("QS-JAN").count()
Out[8]: 
             0
2021-07-01  19
2021-10-01  81
  • 统计出911数据中不同月份电话次数的变化情况
  • 统计出911数据中不同月份不同类型的电话的次数的变化情况

代码1

import pandas as pd
from matplotlib import pyplot as plt

# 读取数据
df = pd.read_csv("./911.csv")

# 将时间字符串转换成时间序列
df["timeStamp"] = pd.to_datetime(df["timeStamp"])
# 将时间序列设置为索引
df.set_index("timeStamp",inplace=True)

print(df.head())

# 统计出911数据中不同月份电话次数(resample重采样取每个月的数据为一组)
count_by_month = df.resample("M").count()["title"]
print(count_by_month)

# 画图
_x = count_by_month.index
_y = count_by_month.values

# dir产看到当前对象拥有哪些方法
# for i in _x:
#     print(dir(i))
#     break

_x = [i.strftime("%Y%m%d") for i in _x]

# 图片大小
plt.figure(figsize=(20,8),dpi=80)

# 画折线图
plt.plot(range(len(_x)),_y)

# 画x刻度
plt.xticks(range(len(_x)),_x,rotation=45)


# 显示
plt.show()

效果图:

在这里插入图片描述

代码2

import pandas as pd
from matplotlib import pyplot as plt
import numpy as np


# 读取数据
df = pd.read_csv("./911.csv")


# 将时间字符串转换成时间序列
df["timeStamp"] = pd.to_datetime(df["timeStamp"])


# 添加列
temp_list = df["title"].str.split(": ").tolist()
cate_list = [i[0] for i in temp_list]
df["cate"] = pd.DataFrame(np.array(cate_list).reshape(df.shape[0],1))


# 将时间序列设置为索引
df.set_index("timeStamp",inplace=True)

# 设置图片大小
plt.figure(figsize=(20,8),dpi=80)


for group_name,group_data in df.groupby(by="cate"):
    
    # 对不同的分类都进行绘图
    count_by_month = group_data.resample("M").count()["title"]


    # 画图
    _x = count_by_month.index
    _y = count_by_month.values

    # 从时间对象转换成格式化字符串
    _x = [i.strftime("%Y%m%d") for i in _x]

    # 画折线图
    plt.plot(range(len(_x)),_y,label=group_name)

# 设置x刻度
plt.xticks(range(len(_x)),_x,rotation=45)
# 添加标识信息
plt.legend(loc="best")

# 显示图片
plt.show()

效果图:

在这里插入图片描述

  • 现在我们有北上广、深圳、和沈阳5个城市空气质量数据,请绘制出5个城市的PM2.5随时间的变化情况

  • 观察这组数据中的时间结构,并不是字符串,这个时候我们应该怎么办?

  • 数据来源: https://www.kaggle.com/uciml/pm25-data-for-five-chinese-cities

  • 之前所学习的DatetimeIndex可以理解为时间戳,那么PeriodIndex可以理解为时间段

  • periods=pd.PeriodIndex(year=data[“year”],month=data[“month”],day=data[“day”],hour=data[“hour”],freq=“H”)

  • 那么如果给这个时间段降采样呢?

  • data = df.set_index(periods).resample(“10D”).mean()

  • 数据格式:

      No	year  month	day	hour season	PM_Dongsi	PM_Dongsihuan	PM_Nongzhanguan	PM_US Post	DEWP	HUMI	PRES	TEMP	cbwd	Iws	precipitation	Iprec
      1	2010	1	1	0	 4	    NA	      NA	NA	NA	-21	43	1021	-11	NW	1.79	0	0
      2	2010	1	1	1	 4	    NA	      NA	NA	NA	-21	47	1020	-12	NW	4.92	0	0
    

代码:

import pandas as pd
from matplotlib import pyplot as plt

file_path = "./PM2.5/BeijingPM20100101_20151231.csv"

# 准备数据
df = pd.read_csv(file_path)
# print(df.info())
# 将不同列数据拼凑为时间段
# 把分开的时间字符串通过PeriodIndex的方法转换为pandas的事件类型
period = pd.PeriodIndex(year=df["year"],month=df["month"],day=df["day"],hour=df["hour"],freq="H")

df["datetime"] = period
# print(period)
# print(type(period))
print(df.head(10))

# 把datetime设置为索引,inplace修改原数据
df.set_index("datetime",inplace=True)

# 进行降采样(mean取降采样前到降采样后,缺失数据的均值)
df = df.resample("7D").mean() # DataFrame默认对索引降采样

# 处理(删除)缺失数据
data = df["PM_US Post"]
data_china = df["PM_Dongsi"]

# 画图
_x = data.index
_x_china = [i.strftime("%Y%m%d") for i in data_china.index]
_x = [i.strftime("%Y%m%d") for i in _x]
_y = data.values
_y_china = data_china.values

# 设置图片大小
plt.figure(figsize=(20,8),dpi=80)


# 画折线图
plt.plot(range(len(_x)),_y,label="US_POST")
plt.plot(range(len(_x_china)),_y_china,label="CN_POST")

# 设置x刻度
plt.xticks(range(0,len(_x),10),list(_x)[::10],rotation=45)

plt.legend(loc="best")

# 画图
plt.show()

效果图:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46456049/article/details/108931389