pandas基础

介绍

基于Numpy构建,为数据分析而存在
    一位数组series+二维数组dataframe
    可直接读取数据并做处理
    兼容各种数据库
    支持各种分析算法

series

数据结构

Series 是带有标签的一维数组,可以保存任何数据类型(整数,字符串,浮点数,Python对象等),轴标签统称为索引
        s = pd.Series(np.random.rand(5))
            s.index
            s.values
        核心:series相比于ndarray,是一个自带索引index的数组 → 一维数组 + 对应索引
        当只看series的值的时候,就是一个ndarray
        series和ndarray较相似,索引切片功能差别不大
        series和dict相比,series更像一个有顺序的字典(dict本身不存在顺序),其索引原理与字典相似(一个用key,一个用index)

创建方法

创建方法一:由字典创建,字典的key就是index,values就是values
            dic = {'a':1 ,'b':2 , 'c':3, '4':4, '5':5}
            s = pd.Series(dic)
        创建方法二:由数组创建(一维数组)
            arr = np.random.randn(5)
            s = pd.Series(arr)
        创建方法三:由标量创建
            s = pd.Series(10, index = range(4))

名称属性:name

位置下标 类似序列

无法用s[-1]这种方式取值
        s[0]

标签索引

根据标签查值
        s['a']
        如果需要选择多个标签的值,用[[]]来表示(相当于[]中包含一个列表)
            多标签索引结果是新的数组

切片索引

s2[:-1]
        s1[1:4]
        下标索引做切片,和list写法一样

布尔型索引

print(s[s > 50])

数据查看

s.head(10)
        s.tail()

重新索引reindex

是返回新的数据对象
        fill_value参数:填充缺失值的值

Series对齐

series 和 ndarray 之间的主要区别是,Series 上的操作会根据标签自动对齐
        index顺序不会影响数值计算,以标签来计算
        空值和任何值计算结果扔为空值

删除:.drop

s.drop(['g','j'])
        drop 删除元素之后返回副本(inplace=False)

添加

直接通过下标索引/标签index添加值
            s1[5] = 100
        通过.append方法,直接添加一个数组
            s1.append(s2)
            .append方法生成一个新的数组,不改变之前的数组

修改

s['a'] = 100

dataframe

数据结构

ataframe是一个表格型的数据结构,“带有标签的二维数组”。
        Dataframe带有index(行标签)和columns(列标签)
        .columns查看列标签
        .index查看行标签
        .values查看值,数据类型为ndarray

创建方法

Dataframe 创建方法一:由数组/list组成的字典
        Dataframe 创建方法二:由Series组成的字典
        ataframe 创建方法三:通过二维数组直接创建
        Dataframe 创建方法四:由字典组成的列表
        Dataframe 创建方法五:由字典组成的字典

选择行与列

data1 = df['a']
            按照列名选择列,只选择一列输出Series,选择多列输出Dataframe
        data3 = df.loc['one']
            按照index选择行,只选择一行输出Series,选择多行输出Dataframe
        核心笔记:df[col]一般用于选择列,[]中写列名
        核心笔记:df.loc[label]主要针对index选择行,同时支持指定index,及默认数字index
        df.iloc[]
            按照整数位置(从轴的0到length-1)选择行
            切片索引
                df.iloc[1:3]

选择列

data1 = df['a']

按index选择行

data1 = df1.loc['one']
        切片法选择行
            data3 = df[:1]

按整数位置选择行

布尔型索引

b2 = df['a'] > 50
        和Series原理相同

多重索引:比如同时索引行和列

先选择列再选择行 —— 相当于对于一个数据,先筛选字段,再选择数据量
        df['a'].loc[['one','three']]
        df[df['a'] < 50].iloc[:2]

数据查看、转置

df.head(2)
        df.tail()
        df.T

添加与修改

df.loc[4] = 20
        修该列名称
            .columns=['','']
        修改行名称
            .index=['','']

删除 del / drop()

del语句 - 删除列
            del df['a']
        drop()删除行,inplace=False → 删除后生成新的数据,不改变原数据
            df.drop([1,2])
        drop()删除列,需要加上axis = 1,inplace=False → 删除后生成新的数据,不改变原数据
            df.drop(['d'], axis = 1)

对齐

DataFrame对象之间的数据自动按照列和索引(行标签)对齐
        df1 + df2

按值排序

df1.sort_values(['a'], ascending = True)
            升序

索引排序

df1.sort_index()

时间

时间模块

datetime.date:date对象
            today = datetime.date.today()
        datetime.datetime:datetime对象
            now = datetime.datetime.now()
        datetime.timedelta:时间差
            yestoday = today - datetime.timedelta(1)
            时间差主要用作时间的加减法,相当于可被识别的时间“差值”
            t2-t1
                相减得到时间差 —— timedelta

parser.parse:日期字符串转换

parse('2000-1-1')
            parse('5/1/2014')
            parse('Jan 31, 1997 10:45 PM')
            各种格式可以解析,但无法支持中文
            from dateutil.parser import parse

时刻数据

pd.Timestamp()

pd.Timestamp('2017-12-21' )
            直接生成pandas的时刻数据 → 时间戳
            数据类型为 pandas的Timestamp
            时刻数据代表时间点,是pandas的数据类型,是将值与时间点相关联的最基本类型的时间序列数据

pd.to_datetime

pd.to_datetime('2017-12-21')
            pd.to_datetime():如果是单个时间数据,转换成pandas的时刻数据,数据类型为Timestamp
            多个时间数据,将会转换为pandas的DatetimeIndex
                当一组时间序列中夹杂其他格式数据,可用errors参数返回
                errors = 'ignore':不可解析时返回原始输入,这里就是直接生成一般数组
                t4 = pd.to_datetime(date3, errors = 'coerce')
                errors = 'coerce':不可扩展,缺失值返回NaT(Not a Time),结果认为DatetimeIndex

时间戳索引

pd.DatetimeIndex()与TimeSeries时间序列
            直接生成时间戳索引,支持str、datetime.datetime
        单个时间戳为Timestamp,多个时间戳为DatetimeIndex

日期

pd.date_range() 日期范围:生成日期范围

2种生成方式:①start + end; ②start/end + periods
            默认频率:day
            直接生成DatetimeIndex
                start:开始时间
                end:结束时间
                periods:偏移量
                freq:频率,默认天
                    freq = 'B'
                        每工作日
                    freq = 'H'
                        每小时
                    freq = 'T'
                        每分
                    freq = 'S'
                        每秒
                     freq = 'W-MON'
                        W-MON:从指定星期几开始算起,每周
                        星期几缩写:MON/TUE/WED/THU/FRI/SAT/SUN
                    freq = 'Q-DEC')
                        Q-月:指定月为季度末,每个季度末最后一月的最后一个日历日
                        A-月:每年指定月份的最后一个日历日
                        月缩写:JAN/FEB/MAR/APR/MAY/JUN/JUL/AUG/SEP/OCT/NOV/DEC
                        所以Q-月只有三种情况:1-4-7-10,2-5-8-11,3-6-9-12
                        BM:每月最后一个工作日
                         BQ-月:指定月为季度末,每个季度末最后一月的最后一个工作日
                        BA-月:每年指定月份的最后一个工作日
                        M:每月第一个日历日
                        Q-月:指定月为季度末,每个季度末最后一月的第一个日历日
                        A-月:每年指定月份的第一个日历日
                         BM:每月第一个工作日
                        BQ-月:指定月为季度末,每个季度末最后一月的第一个工作日
                        BA-月:每年指定月份的第一个工作日
                    freq = '7D'
                        7天
                    freq = '2h30min'
                        2小时30分钟
                tz:时区
                normalize:时间参数值正则化到午夜时间戳
                closed:默认为None的情况下,左闭右闭,left则左闭右开,right则左开右闭
            pd.bdate_range()默认频率为工作日
        pd.date_range()-日期范围:频率(1)
        pd.date_range()-日期范围:频率(2)
         pd.date_range()-日期范围:复合频率
        asfreq:时期频率转换
            ts.asfreq('4H',method = 'ffill')
                改变频率,这里是D改为4H
                method:插值模式,None不插值,ffill用之前值填充,bfill用之后值填充
        pd.date_range()-日期范围:超前/滞后数据
        pd.Period()创建时期
        pd.period_range()创建时期范围
        asfreq:频率转换
        时间戳与时期之间的转换:pd.to_period()、pd.to_timestamp()

时间序列

索引及切片

索引

ts[0]
                ts[:2]

切片

ts['2017/1/5':'2017/1/10']
            重复索引的时间序列
                index有重复,is_unique检查 → values唯一,index不唯一
                通过groupby做分组,重复的值这里用平均值处理

重采样

.resample()
                ts.resample('5D'):得到一个重采样构建器,频率改为5天
                ts.resample('5D').sum():得到一个新的聚合后的Series,聚合方式为求和
                freq:重采样频率 → ts.resample('5D')
                .sum():聚合方法

降采样

closed:各时间段哪一端是闭合(即包含)的,默认 左闭右闭

升采样及插值

ts.resample('15T').asfreq()
                .asfreq():不做填充,返回Nan
            ts.resample('15T').ffill()
                .ffill():向上填充
            ts.resample('15T').bfill()
                .bfill():向下填充
            低频转高频,主要是如何插值

时期重采样 - Period

ts.resample('3M').sum()
                降采样
            ts.resample('15D').ffill()
                升采样

将一列时间数据的天数取出来

df['date'] =pd.to_datetime(df['update_time']).dt.day

数值计算和统计基础

基本参数:axis、skipna

np.nan :空值
        .mean()计算均值
            只统计数字列
            df.mean(axis=1)
                axis参数:默认为0,以列来计算,axis=1,以行来计算,这里就按照行来汇总了
            df.mean(skipna=False)
                 skipna参数:是否忽略NaN,默认True,如False,有NaN的列统计结果仍未NaN

主要数学计算方法,可用于Series和DataFrame(1)

print(df.count(),'→ count统计非Na值的数量\n')
        print(df.min(),'→ min统计最小值\n',df['key2'].max(),'→ max统计最大值\n')
        print(df.quantile(q=0.75),'→ quantile统计分位数,参数q确定位置\n')
            (df.quantile(q=0.75)
            用于标准化数据,去除异常值的函数会用到
        print(df.sum(),'→ sum求和\n')
        print(df.mean(),'→ mean求平均值\n')
        print(df.median(),'→ median求算数中位数,50%分位数\n')
        print(df.std(),'\n',df.var(),'→ std,var分别求标准差,方差\n')
        print(df.skew(),'→ skew样本的偏度\n')
        print(df.kurt(),'→ kurt样本的峰度\n')

主要数学计算方法,可用于Series和DataFrame(2)

cumsum样本的累计和
        cumprod样本的累计积
        cummax,cummin分别求累计最大值,累计最小值

唯一值:.unique()

把序列中去重

值计数:.value_counts()

pd.value_counts(sc, sort = False)
        把序列中每个字符出现的次数做统计

成员资格:.isin()

判断序列中的数据是否与另一个序列中的数据相同

文本数据

通过str访问,且自动排除丢失/ NA值

print(s.str.count('b'))
        # 直接通过.str调用字符串方法
        # 可以对Series、Dataframe使用
        # 自动过滤NaN值
        # df.columns是一个Index对象,也可使用.str

字符串常用方法(1) - lower,upper,len,startswith,endswith

print(s.str.lower(),'→ lower小写\n')
        print(s.str.upper(),'→ upper大写\n')
        print(s.str.len(),'→ len字符长度\n')
        print(s.str.startswith('b'),'→ 判断起始是否为a\n')
        print(s.str.endswith('3'),'→ 判断结束是否为3\n')

字符串常用方法(2) - strip

print(s.str.strip())  # 去除字符串中的空格
        print(s.str.lstrip())  # 去除字符串中的左空格
        print(s.str.rstrip())  # 去除字符串中的右空格
    字符串常用方法(3) - replace
    字符串常用方法(4) - split、rsplit
     字符串索引

merge , join

merge合并 → 类似excel的vlookup

参数how → 合并方式
            pd.merge(df3, df4,on=['key1','key2'], how = 'inner')
            inner:默认,取交集
            outer:取并集,数据缺失范围NaN
            left:按照df3为参考合并,数据缺失范围NaN
            right:按照df4为参考合并,数据缺失范围NaN
        参数 left_on, right_on, left_index, right_index → 当键不为一个列时,可以单独设置左键与右键
        参数 sort

参数how → 合并方式

参数 left_on, right_on, left_index, right_index → 当键不为一个列时,可以单独设置左键与右键
    sort
    pd.join() → 直接通过索引链接

concat, combine_first

连接:concat
        默认axis=0,行+行
        axis=1,列+列,成为一个Dataframe

连接方式:join,join_axes

# join:{'inner','outer'},默认为“outer”。如何处理其他轴上的索引。outer为联合和inner为交集。
        # join_axes:指定联合的index

覆盖列名

keys:序列,默认值无。使用传递的键作为最外层构建层次索引
        axis = 1, 覆盖列名

修补 pd.combine_first()

# 根据index,df1的空值被df2替代
        # 如果df2的index多于df1,则更新到df1上,比如index=['a',1]

去重和替换

去重 .duplicated

s.duplicated()
            判断是否重复
        s[s.duplicated() == False]
            通过布尔判断,得到不重复的值
    drop.duplicates移除重复
        inplace参数:是否替换原值,默认False

替换 .replace

# 可一次性替换一个值或多个值
        # 可传入列表或字典

数据分组

分组

分组统计 - groupby功能
        ① 根据某些条件将数据拆分成组
        ② 对每个组独立应用函数
        ③ 将结果合并到一个数据结构中
        Dataframe在行(axis=0)或列(axis=1)上进行分组,将一个函数应用到各个分组并产生一个新值,然后函数执行结果被合并到最终的结果对象中。
        df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)

分组 - 可迭代对象

其他轴上的分组
    通过字典或者Series分组

通过函数分组

分组计算函数方法
        print(grouped.first(),'→ first:非NaN的第一个值\n')
        print(grouped.last(),'→ last:非NaN的最后一个值\n')
        print(grouped.sum(),'→ sum:非NaN的和\n')
        print(grouped.mean(),'→ mean:非NaN的平均值\n')
        print(grouped.median(),'→ median:非NaN的算术中位数\n')
        print(grouped.count(),'→ count:非NaN的值\n')
        print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')
        print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')
        print(grouped.prod(),'→ prod:非NaN的积\n')

多函数计算:agg()

print(df.groupby('a')['b'].agg({'result1':np.mean,'result2':np.sum}))

分组转换及一般性“拆分-应用-合并”

数据分组转换,transform
    通过分组、合并,得到一个包含均值的Dataframe
    一般化Groupby方法:apply
    pandas.cut
        用来把一组数据分割成离散的区间。

透视表及交叉表

透视表:pivot_table

pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
        # data:DataFrame对象
        # values:要聚合的列或列的列表
        # index:数据透视表的index,从原数据的列中筛选
        # columns:数据透视表的columns,从原数据的列中筛选
        # aggfunc:用于聚合的函数,默认为numpy.mean,支持numpy计算方法
        # 这里就分别以date、key共同做数据透视,值为values:统计不同(date,key)情况下values的平均值
        # aggfunc=len(或者count):计数

交叉表:crosstab

# 默认情况下,crosstab计算因子的频率表,比如用于str的数据透视分析
        # pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)
        # 如果crosstab只接收两个Series,它将提供一个频率表。
        # 用A的唯一值,统计B唯一值的出现次数
        # normalize:默认False,将所有值除以值的总和进行归一化 → 为True时候显示百分比
        # values:可选,根据因子聚合的值数组
        # aggfunc:可选,如果未传递values数组,则计算频率表,如果传递数组,则按照指定计算
        # 这里相当于以A和B界定分组,计算出每组中第三个系列C的值
        # margins:布尔值,默认值False,添加行/列边距(小计)

文件读取

读取普通分隔数据:read_table

可以读取txt,csv

# delimiter:用于拆分的字符,也可以用sep:sep = ','
        # header:用做列名的序号,默认为0(第一行)
        # index_col:指定某列为行索引,否则自动索引0, 1, .....
        # read_table主要用于读取简单的数据,txt/csv

读取csv数据:read_csv

# 先熟悉一下excel怎么导出csv
        # 大多数情况先将excel导出csv,再读取
        # 读取excel数据:read_excel
        # io :文件路径。
        # sheetname:返回多表使用sheetname=[0,1],若sheetname=None是返回全表 → ① int/string 返回的是dataframe ②而none和list返回的是dict
        # header:指定列名行,默认0,即取第一行
        # index_col:指定列为索引列,也可以使用u”strings”