Pandas数据类型
学习目标
- 知道Pandas中都有哪些数据类型和数据结构,并知道数据类型和数据结构之间的关系
- 知道时间日期类型作为索引的数据集可以基于时间范围来选取子集
- 知道时间差类型索引的数据集可以基于时间差范围来选取子集
1 一般类型
Pandas数据类型 | Python类型 | 说明 |
---|---|---|
object | str | 字符串 |
int64 | int | 整数 |
float64 | float | 浮点数 |
bool | bool | 布尔值 |
category | 无原生类型 | 分类类型 |
datetime | 无原生类型 | 时间日期类型 |
timedelta | 无原生类型 | 时间差类型 |
-
pandas是基于numpy构建的包,所以pandas中的数据类型都是基于Numpy中的ndarray类型实现的
-
Pandas中的数据结构对象和数据类型对象:
- dataframe 表 【数据结构】
- series 列【数据结构】
- object --> python str 字符串 【数据类型】
- int64 --> python int 整数 【数据类型】
- float64 --> python float 小数 【数据类型】
- bool --> python bool True False 【数据类型】
- datetime64 --> python datetime 时间日期 【数据类型】
- timedelta[ns]–> 两个时间点之间相距的时间差,单位是纳秒 【数据类型】
- category --> 特定分类数据类型,比如性别分为男、女、其他 【数据类型】
- series 列【数据结构】
- dataframe 表 【数据结构】
-
字符串object 、整数int、小数float 以及 布尔值bool类型都是比较常见的一般类型;本章节将详细介绍不常见的 时间类型 以及 时间差类型
import pandas as pd # 加载印度城市空气质量数据集 df = pd.read_csv('../data/city_day.csv') # 查看数据集各列及各自的数据类型 df.info() # 数据结果如下 <class 'pandas.core.frame.DataFrame'> DatetimeIndex: 29531 entries, 2015-01-01 to 2020-07-01 Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 City 29531 non-null object 1 PM2.5 24933 non-null float64 2 PM10 18391 non-null float64 3 NO 25949 non-null float64 4 NO2 25946 non-null float64 5 NOx 25346 non-null float64 6 NH3 19203 non-null float64 7 CO 27472 non-null float64 8 SO2 25677 non-null float64 9 O3 25509 non-null float64 10 Benzene 23908 non-null float64 11 Toluene 21490 non-null float64 12 Xylene 11422 non-null float64 13 AQI 24850 non-null float64 14 AQI_Bucket 24850 non-null object dtypes: float64(13), object(2) memory usage: 3.6+ MB
2 类型转换
通过
astype()
或to_numeric()
实现类型转换
2.1 seriers.astype函数转换数据类型
astype函数是通用函数,可用于把DataFrame中的任何列(Series)转换为其他dtype;可以向astype方法提供任何内置类型或numpy类型来转换列(Series)的数据类型
-
astype函数使用
print(df['PM2.5'].astype(dtype=str)) print(df['PM2.5'].astype(dtype=object)) # 以上效果相同, 输出结果如下 0 NaN 1 NaN 2 NaN 3 NaN 4 NaN ... 29526 15.02 29527 24.38 29528 22.91 29529 16.64 29530 15 Name: PM2.5, Length: 29531, dtype: object
-
astype注意点
astype函数要求DataFrame列的数据类型必须相同,当有些数据中有缺失,但不是NaN时(如’missing’,'null’等),会使整列数据变成字符串类型而不是数值型,这个时候就会报错
df2 = df.head().copy() # 创造包含'missing'为缺失值的数据,批量替换第1、3、5行中NO列的值为字符串'missing' df2.loc[::2, 'NO'] = 'missing' print(df2) print(df2['NO'].dtypes) # 输出结果如下 City Date PM2.5 PM10 ... Toluene Xylene AQI AQI_Bucket 0 Ahmedabad 2015-01-01 NaN NaN ... 0.02 0.00 NaN NaN 1 Ahmedabad 2015-01-02 NaN NaN ... 5.50 3.77 NaN NaN 2 Ahmedabad 2015-01-03 NaN NaN ... 16.40 2.25 NaN NaN 3 Ahmedabad 2015-01-04 NaN NaN ... 10.14 1.00 NaN NaN 4 Ahmedabad 2015-01-05 NaN NaN ... 18.89 2.78 NaN NaN [5 rows x 16 columns] object
-
此时运行下面的代码会报错
ValueError: could not convert string to float: 'missing'
,无法使用astype函数进行类型转换;这个时候我们可以使用to_numeric
函数print(df2['NO'].astype(float))
2.2 pd.to_numeric函数字符串转数字类型
astype函数要求DataFrame列的数据类型必须相同,当有些数据中有缺失,但不是NaN时(如’missing’,'null’等),会使整列数据变成字符串类型而不是数值型,这个时候可以使用to_numeric处理
-
pd.to_numeric函数的参数errors, 它决定了当该函数遇到无法转换的数值时该如何处理
- 默认情况下,该值为raise,如果to_numeric遇到无法转换的值时,会抛出异常
- coerce: 如果to_numeric遇到无法转换的值时,会返回NaN值
- ignore: 如果to_numeric遇到无法转换的值时会放弃转换,什么都不做
# 转换成float类型, 抛出异常:ValueError: Unable to parse string "missing" at position 0 # print(pd.to_numeric(df2['NO'])) # 无法转换的值返回NaN print(pd.to_numeric(df2['NO'], errors='coerce')) # 无法转换的值返回原值 print(pd.to_numeric(df2['NO'], errors='ignore')) # 输出结果 0 NaN 1 0.97 2 NaN 3 1.70 4 NaN Name: NO, dtype: float64 0 missing 1 0.97 2 missing 3 1.7 4 missing Name: NO, dtype: object
3 datetime时间类型
3.1 Python中的datetime类型
-
python没有原生的datetime数据类型,需要使用datetime包
from datetime import datetime now = datetime.now() someday = datetime(2020, 1, 1) print(now) print(type(now)) print(someday) print(type(someday)) # 返回输出结果如下 2024-02-07 09:50:20.461322 <class 'datetime.datetime'> 2020-01-01 00:00:00 <class 'datetime.datetime'>
3.2 读取数据时指定列为datetime类型
-
读取数据集时,使用参数
parse_dates=[列下标/列名]
直接将转为datetime类型# 加载印度城市空气质量数据集 # df = pd.read_csv('../data/city_day.csv', parse_dates=[1]) df = pd.read_csv('../data/city_day.csv', parse_dates=['Date']) print(df['Date'].head()) # 数据结果如下 0 2015-01-01 1 2015-01-02 2 2015-01-03 3 2015-01-04 4 2015-01-05 Name: Date, dtype: datetime64[ns]
3.3 pd.to_datetime将字符串转换为时间日期类型
df = pd.read_csv('../data/city_day.csv')
# 查看Date列数据类型
print(df['Date'].head())
# 将Date列数据转换为时间类型
df['Date'] = pd.to_datetime(df['Date'])
print(df['Date'].head())
# 输出结果如下
0 2015-01-01
1 2015-01-02
2 2015-01-03
3 2015-01-04
4 2015-01-05
Name: Date, dtype: object
0 2015-01-01
1 2015-01-02
2 2015-01-03
3 2015-01-04
4 2015-01-05
Name: Date, dtype: datetime64[ns]
3.4 提取datetime类型数据中具体时间
-
由datetime构成的Seriers提取时间日期中的各个部分
# print(df['Date'].year) # 报错 print(df['Date'].dt.year) print(df['Date'].dt.month) print(df['Date'].dt.day) print(df['Date'].dt.hour) print(df['Date'].dt.minute) print(df['Date'].dt.second) print(df['Date'].dt.quarter) # 季度 print(df['Date'].dt.dayofweek + 1) # 星期,与 df['Date'].dt.weekday+1 相同 print(df['Date'].dt.weekday + 1) # 星期
-
由datetime构成的Seriers的其中一个数据提取时间日期中的各个部分
d = pd.to_datetime('2020-06-20') print(d) # d ==> 2020-06-20 00:00:00 print(type(d)) # <class 'pandas._libs.tslibs.timestamps.Timestamp'> print(d.year) print(d.month) print(d.day) print(d.hour) print(d.minute) print(d.second) print(d.quarter) # 季度 print(d.weekday()) # 星期几,与d.dayofweek相同 0是星期一 1是星期二 6是星期日 print(d.dayofweek + 1)
3.5 datetime类型的Seriers进行时间计算
-
datetime类型的日期可以直接进行时间计算:
- 可以直接使用聚合函数
- 也可以直接进行时间差运算
# 直接调用聚合函数 print(df['Date'].min()) # 直接进行时间差运算 # 返回时间差类型数据构成的Seriers print(df['Date'] - df['Date'].min()) # 输出结果如下 2015-01-01 00:00:00 0 0 days 1 1 days 2 2 days 3 3 days 4 4 days ... 29526 2004 days 29527 2005 days 29528 2006 days 29529 2007 days 29530 2008 days Name: Date, Length: 29531, dtype: timedelta64[ns]
3.6 datetime类型数据列作为df索引
-
datetime类型数据列作为df索引可以通过具体的时间查询df子集
# 加载数据集,设定时间类型列为索引列 df = pd.read_csv('../data/city_day.csv', index_col='Date', parse_dates=True) # 对索引进行重新排序 df = df.sort_index() # 必要步骤 print(df['2018']) # 索引排序之后,才能按年取子集df print(df['2016-06']) # 按年月取子集df:所有符合条件的完整行数据 print(df.loc['2015-3-4 22': '2016-1-1 23:45:00']) # 按时间范围取子集 # 输出结果如下 City PM2.5 PM10 ... Xylene AQI AQI_Bucket Date ... 2018-01-01 Hyderabad 57.70 119.64 ... 3.74 122.0 Moderate 2018-01-01 Delhi 303.41 415.09 ... 0.24 462.0 Severe 2018-01-01 Ahmedabad 84.46 NaN ... 6.33 278.0 Poor 2018-01-01 Visakhapatnam 59.73 99.04 ... 0.66 131.0 Moderate 2018-01-01 Talcher NaN NaN ... NaN NaN NaN ... ... ... ... ... ... ... ... 2018-12-31 Brajrajnagar 113.28 187.85 ... NaN 236.0 Poor 2018-12-31 Ahmedabad 80.54 NaN ... 6.93 744.0 Severe 2018-12-31 Lucknow 248.51 NaN ... NaN 403.0 Severe 2018-12-31 Talcher 84.30 263.09 ... NaN 200.0 Moderate 2018-12-31 Amritsar 78.42 186.41 ... 9.09 184.0 Moderate [6471 rows x 15 columns] City PM2.5 PM10 ... Xylene AQI AQI_Bucket Date ... 2016-06-01 Patna 68.89 NaN ... 0.45 147.0 Moderate 2016-06-01 Lucknow 138.37 NaN ... NaN 207.0 Poor 2016-06-01 Ahmedabad NaN NaN ... NaN NaN NaN 2016-06-01 Delhi 76.56 251.87 ... NaN 283.0 Poor 2016-06-01 Hyderabad 39.88 NaN ... 0.23 111.0 Moderate ... ... ... ... ... ... ... ... 2016-06-30 Mumbai NaN NaN ... NaN NaN NaN 2016-06-30 Lucknow 89.00 NaN ... NaN 59.0 Satisfactory 2016-06-30 Patna 45.54 NaN ... 0.17 85.0 Satisfactory 2016-06-30 Delhi 69.65 103.25 ... NaN 190.0 Moderate 2016-06-30 Ahmedabad 30.16 NaN ... 0.00 256.0 Poor [270 rows x 15 columns] City PM2.5 PM10 ... Xylene AQI AQI_Bucket Date ... 2015-03-05 Delhi 106.57 196.19 ... 10.65 275.0 Poor 2015-03-05 Hyderabad NaN NaN ... 1.01 NaN NaN 2015-03-05 Lucknow NaN NaN ... NaN NaN NaN 2015-03-05 Ahmedabad 173.01 NaN ... 4.13 780.0 Severe 2015-03-05 Chennai NaN NaN ... NaN NaN NaN ... ... ... ... ... ... ... ... 2016-01-01 Bengaluru 56.40 95.08 ... NaN 101.0 Moderate 2016-01-01 Delhi 295.71 476.09 ... 0.00 463.0 Severe 2016-01-01 Hyderabad 232.83 108.20 ... 2.41 387.0 Very Poor 2016-01-01 Patna 553.63 NaN ... 2.34 619.0 Severe 2016-01-01 Lucknow 203.43 NaN ... NaN 375.0 Very Poor [2372 rows x 15 columns]
4 timedelta时间差类型
4.1 Python中的timedelta类型
-
python没有原生的timedelta数据类型,需要使用datetime包
from datetime import datetime t1 = datetime.now() t2 = datetime(2020, 1, 1) diff = t1 - t2 # 时间差类型 print(diff) print(type(diff)) # 输出结果如下 1498 days, 10:07:14.970549 <class 'datetime.timedelta'>
4.2 Pandas中的timedelta类型
-
两个时间Seriers相减即可得到timedelta类型数据构成的Seriers对象
# 加载数据,指定下标为1的列为时间日期类型 df = pd.read_csv('../data/city_day.csv', parse_dates=[1]) # 当前日期减去数据集中最早的日期,即可得到时间差;同时赋值给新的列 df['ref_date'] = df['Date'] - df['Date'].min() print(df['ref_date'].head()) # 输出结果如下 0 0 days 1 1 days 2 2 days 3 3 days 4 4 days Name: ref_date, dtype: timedelta64[ns]
4.3 pd.to_timedelta函数转换timedelta类型
-
timedelta类型转换为字符串类型
s1 = df['ref_date'].astype(str) print(s1) # 返回结果如下 0 0 days 1 1 days 2 2 days 3 3 days 4 4 days ... 29526 2004 days 29527 2005 days 29528 2006 days 29529 2007 days 29530 2008 days Name: ref_date, Length: 29531, dtype: object
-
字符串类型转换为timedelta类型
s2 = pd.to_timedelta(s1) print(s2) # 返回结果如下 0 0 days 1 1 days 2 2 days 3 3 days 4 4 days ... 29526 2004 days 29527 2005 days 29528 2006 days 29529 2007 days 29530 2008 days Name: ref_date, Length: 29531, dtype: timedelta64[ns]
4.4 timedelta类型数据作为df索引
-
如果将timedelta类型数据作为df索引,就可以基于时间差范围来选择数据
# 读取数据,并将下标为1的Date列设为时间类型列 df = pd.read_csv('../data/city_day.csv', parse_dates=[1]) # 获取印度城市德里的子集 df2 = df.query('City=="Delhi"') # 将timedelta类型的Series设置为df的索引 # df2.索引 = Date列 - Date列最早的那一天 df2.index = df2['Date'] - df2['Date'].min() print(df2.head()) # 查看数据集 # 基于时间差范围来选择数据 print(df2['0 days':'4 days']) # 输出结果如下 City Date PM2.5 PM10 ... Toluene Xylene AQI AQI_Bucket Date ... 0 days Delhi 2015-01-01 313.22 607.98 ... 24.86 9.84 472.0 Severe 1 days Delhi 2015-01-02 186.18 269.55 ... 20.09 4.29 454.0 Severe 2 days Delhi 2015-01-03 87.18 131.90 ... 10.23 1.99 143.0 Moderate 3 days Delhi 2015-01-04 151.84 241.84 ... 9.71 3.34 319.0 Very Poor 4 days Delhi 2015-01-05 146.60 219.13 ... 6.21 2.96 325.0 Very Poor [5 rows x 16 columns] City Date PM2.5 PM10 ... Toluene Xylene AQI AQI_Bucket Date ... 0 days Delhi 2015-01-01 313.22 607.98 ... 24.86 9.84 472.0 Severe 1 days Delhi 2015-01-02 186.18 269.55 ... 20.09 4.29 454.0 Severe 2 days Delhi 2015-01-03 87.18 131.90 ... 10.23 1.99 143.0 Moderate 3 days Delhi 2015-01-04 151.84 241.84 ... 9.71 3.34 319.0 Very Poor 4 days Delhi 2015-01-05 146.60 219.13 ... 6.21 2.96 325.0 Very Poor [5 rows x 16 columns]
总结
请对下面的内容 有印象、能找到、能理解、能看懂
1. Pandas中的数据类型
Pandas数据类型 | Python类型 | 说明 |
---|---|---|
object | str | 字符串 |
int64 | int | 整数 |
float64 | float | 浮点数 |
bool | bool | 布尔值 |
category | 无原生类型 | 分类类型 |
datetime | 无原生类型 | 时间日期类型 |
timedelta | 无原生类型 | 时间差类型 |
2. Pandas中数据结构和数据类型的关系
- pandas是基于numpy构建的包,所以pandas中的数据类型都是基于Numpy中的ndarray类型实现的
- Pandas中的数据结构对象和数据类型对象:
- dataframe 表 【数据结构】
- series 列【数据结构】
- object --> python str 字符串 【数据类型】
- int64 --> python int 整数 【数据类型】
- float64 --> python float 小数 【数据类型】
- bool --> python bool True False 【数据类型】
- datetime64 --> python datetime 时间日期 【数据类型】
- series 列【数据结构】
- dataframe 表 【数据结构】
- timedelta[ns]–> 两个时间点之间相距的时间差,单位是纳秒 【数据类型】
3. Pandas数据类型转换基本方法
df['列名'].astype(str)
- 当Seriers对象使用astype函数转换的结果中数据类型不同时,使用to_numeric函数
pd.to_numeric(df['列名'], errors='coerce')
无法转换的值返回NaNpd.to_numeric(df['列名'], errors='ignore')
无法转换的值返回原值
4. datetime时间类型
- datetime时间类型的Seriers来源两种方式:
- 读取时指定
df = pd.read_csv('..xxx.csv', parse_dates=[1])
- 转换
df['Date'] = pd.to_datetime(df['Date'])
- 读取时指定
- 提取datetime时间类型的Seriers中的具体年月日时分秒星期
df['Date'].dt.year
df['Date'].dt.quarter
# 季度df['Date'].dt.dayofweek + 1
# 星期
- 提取datetime时间类型的Seriers中的某一个值的具体年月日时分秒星期
df4['Date'][0].dayofweek+1 # 星期
- datetime时间类型的Seriers可以进行时间计算
- 直接调用聚合函数
df['Date'].max() # 最近的日期
- 计算时间差
df['Date'] - df['Date'].min() # 返回时间差类型数据构成的Seriers
- 直接调用聚合函数
- datetime时间类型的S对象作为索引的两种方式
df = pd.read_csv('..xxx.csv', index_col='Date', parse_dates=True)
df.index = df['date']
- 注意:要对索引进行重新排序 必要步骤
df = df.sort_index()
- datetime时间类型索引可以按照时间范围取子集
df['2018']
df['2016-06']
df.loc['2015-3-4 22': '2016-1-1 23:45:00']
5. timedelta时间差类型
- timedelta时间差类型的创建:
df['date_diff'] = df['Date'] - df['Date'].min()
- 字符串类型转换为时间差类型
s2 = pd.to_timedelta(s1)
- timedelta时间差类型设为索引
df.index = df['Date'] - df['Date'].min()
- 基于时间差范围来选择数据
df['0 days':'4 days']