Python模块之Pandas part1
基本属性
import pandas as pd
# 形状
df.shape
# 行索引
df.index
# 列索引
df.columns
# 值
df.values
# 转置
df.T
# 前N行 默认是5行
df.head()
# 后N行 默认是5行
df.tail()
# 查看类型
df.dtypes
# 指定类型
df.astype(int)
常用操作
import numpy as np
import pandas as pd
df: pd.DataFrame
# 删除指定列 col1, col2
df.drop([col1, col2], axis=1, inplace=True)
# 针对 city name 2列进行去重
df.drop_duplicates(subset=["city", "name"], inplace=True)
# 对Series进行操作 Series.str转成srt 可调用string的方法
df['typecode'].str.endswitch('00') # typecode 以00 结尾
# 对 text 列 使用正则提取 放入rating
df['rating'] = df['text'].str.extract(r'(\d+\.?\d*\/\d+)', expand=False)
# 对1列 拆分成2列
df = pd.DataFrame({'AB': ['A1-B1', 'A2-B2']})
df['A'], df['B'] = df['AB'].str.split('-', 1).str
# 对Series 转成list
df['A'].values.tolist()
索引
# 修改所有行列索引
new_idx = []
new_col = []
df = df(index=new_idx, columns=new_col)
# 修改单个索引 inplace=True 替换原来的
data.rename(index={"0": "股票1", "1":"股票2"}, inplace=True)
data.rename(columns={"city": "cityname", "ccode": "citycode"}, inplace=True)
# 设置新的下标索引
df.reset_index(drop=True)
# 把某列的值设置为索引,设多列 会变成MultiIndex 复合索引 表示多维数据
df.set_inde(keys, drop=True)
取值
# 直接使用行列索引(先列后行)
df["open"][9] # 单个数据
df[['open', 'close']][1:7] # 连续行
df[['open', 'close']][df.index.isin([1, 4, 8])] # 非连续行
# 通过loc 使用索引名 (先行后列)
df.loc["行索引0": "行索引9", "NEW_TYPE":"中类"]
# 通过iloc 使用索引下标 (先行后列)
df.iloc[:3, 1:5]
运算
# 加减乘除 直接使用算术表达式 或者 使用函数 add/sub/mul/div
df["pop_sum"] = df["pop_1"] + df["pop_2"]
# 逻辑运算 > >= < <= == != 得到bool的结构
df[df["pop_sum"] > 10]
# 与(&)或(|)非(~)
df[(df["pop_1"] > 10) & (df["pop_2"] < 50)]
df[(df["pop_1"] > 10) | (df["pop_2"] < 50)]
df[~df["pop_1"] > 10]
# 传入布尔表达式,进行查询过滤
df.query("pop_1 > 10 & pop_2 < 50")
# 返回布尔结构 可做索引
df[df["pop_1"].isin([10, 20, 30, 40])]
# 统计运算 返回每列 常见的统计量 非空数量/平均值/标准差/最大值/最小值/中位数/分位数
df.describe()
# 统计运算 默认对列操作, axis=1 对行操作
df.sum()
- 统计运算(默认对列操作,
axis=1
对行操作)
函数 | 作用(针对非 NaN 值) |
---|---|
sum |
和 |
mean |
平均数 |
median |
中位数 |
min |
最小值 |
max |
最大值 |
mode |
众数 |
abs |
绝对值 |
prod |
Product of values |
std |
标准差 |
var |
方差 |
idxmax |
计算最大值所在的索引 |
idxmin |
计算最小值所在的索引 |
cumsum |
计算前1/2/3/…/n个数的和 |
cumprod |
计算前1/2/3/…/n个数的积 |
cummax |
计算前1/2/3/…/n个数的最大值 |
cummin |
计算前1/2/3/…/n个数的最小值 |
- idxmax / idxmin 调用报错
TypeError: reduction operation 'argmax' not allowed for this dtype
-
从文件中读取数据后, 默认元素类型是object
-
df.dtypes 查询所有列的数据类型
-
读取时使用dtype 或 读取后使用astype转换
-
pd.to_numeric(s, errors=’’") 转成数值
- error = ‘raise’ 无效值 报错
- errors=‘coerce’ 无效值强制转为NaN
- errors=‘ignore’ 异常值忽略
-
自定义运算
df.apply(func, axis=0, args=())
# func: 自定义函数 对行/列进行操作
# agrs: 函数其他参数
# axis=0: 默认是列 1为行运算
- 排序
# 对值排序 根据单个/多个列,进行排序,默认升序
df.sort_values(by=[], ascending=True)
# 对索引排序
df.sort_index(axis=0, ascending=True)
IO 操作
读写csv
pd.read_csv(filepath_or_buffer, sep=",", header="infer", names=None,index_col=None, dtype={}, encoding="utf-8", usecols=None)
-
pd.read_csv()
- 读取csv 文件
- filepath_or_buffer: 文件路径
- sep: 分隔符 默认,
- header: 指定做列索引的行, 默认是 infer (推断)
- names: 添加列名. 有列名的情况下 设置 header=0
- index_col: 指定做行索引的列, 传下标或者列名
- dtype: 指定类型 指定所有 或 特定几列 dict
- usecols: 指定读取的列名 list
- encoding: 编码格式
-
pd.to_csv()
- 写入 csv
- path_or_buf: 路径
- sep: 分隔符, 默认是 ,
- columns: 指定列
- index: 是否写入行索引
- header: 是否写入列索引
- mode: ‘w’ 重写 ‘a’ 追加
- encoding: 编码格式
HDF5 一种容器 可以存放多份数据 通过不同的 key来区分比 csv 读写更快 内存更小
- pd.HDFStore("./test.h5").keys()
- 获取 test.h5 文件所有的 key
- pd.read_hdf()
- 读取 hdf5 文件
- path_or_buf: 路径
- key: 读取的键 单份数据 可不输入
- mode: 打开文件的方式
- pd.to_hdf()
- 写入hdf5 文件
- path_or_buf: 路径
- key: 必须提供 key
- mode: 打开文件的方式
读写json
- pd.read_json()
- 读取 json 文件
- path_or_buf: 路径
- orient: json 文件的数据方式
- ‘split’ : dict like {index -> [index], columns -> [columns], data -> [values]}
- ’records’ : list like [{column -> value}, … , {column -> value}]
- ‘index’ : dict like {index -> {column -> value}}
- ’columns’ : dict like {column -> {index -> value}},默认该格式
- ‘values’ : just the values array
- lines : boolean, default False
- 按照每行读取json对象
- pd.to_json()
- 写入 json
- path_or_buf: 路径
- orient: json 文件的数据方式
读取数据库
import pandas as pd
from sqlalchemy import create_engine
# 使用 sqlalchemy
engine = create_engine(f"mysql+pymysql://{DB_USERNAME}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}")
# 或者 使用 pymysql
import pymysql
db = pymysql.connect(host, port, user, password,database, charset="utf8")
sql = "select * from test_table"
df = pd.read_sql(sql, engine)
# 或者
df = pd.read_sql(sql, db)
缺失值(missing value)处理
缺失值必须是 np.nan
-
判断缺失值是否存在
- df.isnull()
- 配合 np.any() 查看整体是否有空值
- df.notnull()
- df.isnull()
-
找出包含空值的列
- df.isnull().sum()
- 为空 返回True 就是 1 累加>0 的列就含有空值
- df.isnull().apply(np.any)
- df.isnull().sum()
-
df.dropna(axis=‘rows’)
- 删除包含空值的行
- 需要接收返回值
-
df.fillna(value, inplace=True)
- 替换缺失值(均值/中值)
- inplace=True 修改原数据
- 对几列操作 value 传 dict {‘列名’:‘替换值’}
- df.fillna({‘Live’: 111, ‘Task’:222})
缺失值不为 np.nan 先替换再操作
- df.replace(’?’, np.nan)
离散化(结果是 Series)
- pd.qcut(series, bins)
- 按照给定的分组数量,自动切分series
- bins 传分组个数 int
- pd.cut(series,bins)
- 按照给定的切分点分组
- bins 需要自定义分组区间 (传 list)
- pd.get_dummies(data, prefix=None)
- 创建one-hot 编码
- data:array-like, Series, or DataFrame
- prefix:分组名字
合并
- pd.concat([data1, data2], axis=1)
- 按照行/列合并 axis=1 按行拼接
- pd.merge(left, right, how=‘inner’, on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True,suffixes=(’_x’, ‘_y’), copy=True, indicator=False,validate=None)
- 可以指定按照两组数据的共同键值对合并或者左右各自键合并
- 基于一个/多个 key 合并(可以将多个 key 先组合视为一个 key 再合并)
how
: 连接方式left
: A DataFrame objectright
: Another DataFrame objecton
: Columns (names) to join on. Must be found in both the left and right DataFrame objects.- left_on=None, right_on=None:指定左右键
Merge method | SQL Join Name | Description |
---|---|---|
left |
LEFT OUTER JOIN |
Use keys from left frame only |
right |
RIGHT OUTER JOIN |
Use keys from right frame only |
outer |
FULL OUTER JOIN |
Use union of keys from both frames |
inner |
INNER JOIN |
Use intersection of keys from both frames |
交叉透视表
- pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, margins_name=‘All’, dropna=True, normalize=False)
- 交叉表
- index: 指定交叉表的行
- columns: 指定交叉表的列d
- normalize: 默认为 False, ‘index’ 按行计算比例 ‘columns’ 按列计算比例
- pd.pivot_table()
- 透视表
- index
- columns
- values
- aggfunc=‘mean’ 计算平均值 count 计数
分组与聚合
对 df 做 groupby 生成 DataFrameGroupby 对象
做索引后 生成 SeriesGroupby 对象
- df.groupby(key, as_index=False)
- 分组操作
- Key: 分组的列数据,可以多个
- 聚合(sum/min/max/count/mean/std/var)
# 对 color 分组 对 price 求平均值
data.groupby(['color'])['price'].mean()
# 写法 2 Series.groupby(Series)
data['price'].groupby(data['color']).mean()
分类
-
pd.Categorical(values, categories=None, ordered=None, dtype=None, fastpath=False)
-
数字化分类数据, 有效加快分类计算的效率
-
values: list-like
-
categories: 唯一类别
-
ordered: 是否为有序分类
-
属性
- categories: 分类索引
- codes: 对应的分类后的数组值d
- ordered: 顺序
- dtype: 类别
c = pd.Categorical(['a','b','c','a','b','c']) c [a, b, c, a, b, c] Categories (3, object): [a, b, c] c.categories Index(['a', 'b', 'c'], dtype='object') c.codes array([0, 1, 2, 0, 1, 2], dtype=int8) c.ordered False c.dtype CategoricalDtype(categories=['a', 'b', 'c'], ordered=False)
-
-
pd.factorize(values, sort=False, order=None, na_sentinel=-1, size_hint=None)
- 转换为枚举或分类类型
- 返回值
- labels : ndarray
- uniques : ndarray, Index, or Categorical
>>> labels, uniques = pd.factorize(['b', 'b', 'a', 'c', 'b'])
>>> labels
array([0, 0, 1, 2, 0])
>>> uniques
array(['b', 'a', 'c'], dtype=object)
>>> labels, uniques = pd.factorize(['b', 'b', 'a', 'c', 'b'], sort=True)
>>> labels
array([1, 1, 0, 2, 1])
>>> uniques
array(['a', 'b', 'c'], dtype=object)
>>> labels, uniques = pd.factorize(['b', None, 'a', 'c', 'b'])
>>> labels
array([ 0, -1, 1, 2, 0])
>>> uniques
array(['b', 'a', 'c'], dtype=object)
>>> cat = pd.Categorical(['a', 'a', 'c'], categories=['a', 'b', 'c'])
>>> labels, uniques = pd.factorize(cat)
>>> labels
array([0, 0, 1])
>>> uniques
[a, c]
Categories (3, object): [a, b, c]
时间索引
-
pd.to_datetime(arg, errors=‘raise’, dayfirst=False, yearfirst=False, utc=None, box=True, format=None, exact=True, unit=None, infer_datetime_format=False, origin=‘unix’, cache=False)
- 转换成pandas的时间类型 Timestamp
- arg : integer, float, string, datetime, list, tuple, 1-d array, Series
- error: 异常解决办法 {‘ignore’, ‘raise’, ‘coerce’}, default ‘raise’
- dayfirst : boolean, default False.True 10/11/12 -> 2012-11-10
- yearfirst: boolean, default False.True 10/11/12 -> 2010-11-12
- format: 时间戳转为date 格式 %d/%m/%Y
- unit: 时间戳转 date 的精度 default ‘ns’
- origin: ‘unix’, 时间原点为 1970-01-01. 可自定义Timestamp 格式,从设置那天算起
df = pd.DataFrame({'year': [2015, 2016], 'month': [2, 3], 'day': [4, 5]}) pd.to_datetime(df) 0 2015-02-04 1 2016-03-05 dtype: datetime64[ns] pd.to_datetime(1490195805433502912, unit='ns') Timestamp('2017-03-22 15:16:45.433502912') pd.to_datetime([1, 2, 3], unit='D',origin=pd.Timestamp('1960-01-01')) 0 1960-01-02 1 1960-01-03 2 1960-01-04 pd.Timestamp(1513393355.5, unit='s') Timestamp('2017-12-16 03:02:35.500000') # 有空值 结果会变成NaT类型 dates = ['20200401', '20200402', '20200403', np.nan] pd.to_datetime(dates) DatetimeIndex(['2020-04-01', '2020-04-02', '2020-04-03','NaT'], dtype='datetime64[ns]', freq=None)
-
pd.DatetimeIndex()
- 与pd.to_datetime 效果一样
-
pd.Timestamp 类型
- 属性 year,month,weekday,day,hour
- 属性 .week 获取当前日期对应当前年份第几个星期(从 1 开始)
- 方法.weekday() 获取当前日期对应星期几(从 0 开始)
-
pd.date_range(start=None, end=None, periods=None, freq=‘D’, tz=None, normalize=False, name=None, closed=None, **kwargs)
- 生成指定频率的时间序列
- start:开始时间
- end:结束时间
- periods:生成多长的序列
- freq:频率,默认是D(1天), ‘B’ 工作日
- tz: 时区
- close: 默认None 包含start和end, left 只包含start , end 只包含end
参数 含义 D 每日 B 每工作日 H、T或者min、S 时、分、秒 M 每月最后一天 BM 每月最后一个工作日 WOM-1MON, WOM-3FRI 每月第几周的星期几 -
pd.resample()
-
频率转换和时间序列重采样,对象必须具有类似日期时间的索引(DatetimeIndex,PeriodIndex或TimedeltaIndex)
参数 说明 rule 表示重采样频率,例如周’W’,月’M’,季度’Q’,5分钟’5min’,12天’12D’ how=’mean’ 用于产生聚合值的函数名或数组函数,例如‘mean’、‘ohlc’、np.max等,默认是‘mean’,其他常用的值由:‘first’、‘last’、‘median’、‘max’、‘min’ axis=0 默认是纵轴,横轴设置axis=1 fill_method = None 升采样时如何插值,比如‘ffill’、‘bfill’等 closed = ‘right’ 在降采样时,各时间段的哪一段是闭合的,‘right’或‘left’,默认‘right’ label= ‘right’ 在降采样时,如何设置聚合值的标签,例如,9:30-9:35会被标记成9:30还是9:35,默认9:35 loffset = None 面元标签的时间校正值,比如‘-1s’或Second(-1)用于将聚合标签调早1秒 limit=None 在向前或向后填充时,允许填充的最大时期数 kind = None 聚合到时期(‘period’)或时间戳(‘timestamp’),默认聚合到时间序列的索引类型 convention = None 当重采样时期时,将低频率转换到高频率所采用的约定(start或end)。默认‘end’
-
-
pd.rolling_mean(arg, window, min_periods=None, freq=None, center=False, how=None, **kwargs)
- 计算移动平均线
- arg: Series DataFrame
- window: 计算周期
-
pd.ewma(com=None, span=one)
- 指数平均线
- span:时间间隔
-
pd.scatter_matrix(frame, figsize=None)
- 各项指数两两关联散点图
- frame:DataFrame