Python __ Pandas

简介

可以看做是Excel
是基于Numpy的.
优点:处理表格数据(混杂数据)
需要引用:import pandas as pd

Series(无用)

类似于Numpy的一维数组
优点:相较于Nump索引功能强大

输出默认带索引:(当为字典是,,默认键是索引)
s4 = pd.Series([9.53,9.62,9.72])
创建时可以指定索引:
s5 = pd.Series([1, np.nan, 7.0, 'abc'], index=['a','b','c','d'])

DataFrame(常用)

类似于Numpy的二维数组

基本操作

获取行列数据

在 Pandas 中,有多个方法可以选取和重新组合数据,如表所示:

方法 说明
df[val] 从DataFrame中选取单列或多列。val为布尔型数组时,过滤行; val为切片时,行切片
df.loc[val] 通过val选取单行或多行
df.loc[;,val] 通过val选取单列或多列
df.loc[val1,val2] 选取val1行、val2列的值
df.iloc[val] 通过整数位置,选取单行或多行
df.iloc[;,val] 通过整数位置,选取单列或多列
df.iloc[val1, val2] 通过整数位置,选取val1 行、val2列的值

具体说明如下:
1、读取行
如果想从 DataFrame 中获取某一行数据,可以通过位置或名称进行获取。
读取行有三种方法,分别是loc,iloc,ix。

方法名 参数 备注
loc 行标签 可以使用元组
iloc 行号 可以进行切片
ix iloc和loc的并 不推荐使用IX索引器,已弃用

示例:

  1. loc通过行标签索引来确定行的
import pandas as pd
d=[[1,2,3,4],[5,6,7,8]]
index=["one","two"]
df=pd.DataFrame(d, index=index)

print df.loc["one"]
  1. iloc通过行号索引来确定行
import pandas as pd
d=[[1,2,3,4],[5,6,7,8]]
index=["one","two"]
df=pd.DataFrame(d, index=index)

print df.iloc[0]

2、读取列
如果想从 DataFrame 中获取某一列数据为一个 Series, 可以通过类似字典标记或属性的方式:
[]括号里可以是列标签/列号
实例:

print df5['浦发银行'] #也可以是 df5[0]
#2020-10-14 9.53
#2020-10-15 9.62
#2020-10-16 9.72
#Name: 浦发银行, dtype: float64

df5[['浦发银行','民生银行']]  #可以是个元组
#           浦发银行   民生银行
#2020-10-14   9.53     5.33
#2020-10-15   9.62     5.35
#2020-10-16   9.72     5.39
df5[df5['浦发银行'] > 9.6]   # 同时可以进行筛选数据
#           浦发银行   民生银行
#2020-10-15   9.62     5.35
#2020-10-16   9.72     5.39

对某列进行 单值筛选

找出df中A列值为100的所有数据

1 df[df.A==100]
#     A    B    C
# 0    100    a    1

用序列对某列筛选:isin

找出df中A列,值为100、200、300的所有数据

num = [100, 200, 300]
df[df.A.isin(num)]     #筛选出A列值在num列表的数据条
#        A    B    C
# 0    100    a    1
# 1    200    b    2
# 2    300    c    3

对多列 进行筛选

多条件筛选的时候,必须加括号()

  1. 找出df中A列值为100B列值为‘a’的所有数据
df[(df.A==100)&(df.B=='a')]
#        A    B    C
# 0    100    a    1
  1. 找出df中A列值为100B列值为‘b’的所有数据
df[(df.A==100)|(df.B=='b')]
#        A    B    C
# 0    100    a    1
# 1    200    b    2

对行列赋值

对DataFrame中某一列的值进行修改,可通过直接赋值一个标量值或一组值:

df5 = pd.DataFrame({'a':[1,2,3],'b':[5,6,7],
                    'c':[9,10,11],'d':[13,14,15]},
                    index=['x','y','z'])
#    a   b   c   d
#x   1   5   9   13
#y   2   6   10  14
#z   3   7   11  15
df5['d'] = 1  # 对d列赋值为1
#    a   b   c   d
#x   1   5   9   1
#y   2   6   10  1
#z   3   7   11  1

df5['d'] = np.arange(3) # 对d列赋值为np.arange(3)
#    a   b   c   d
#x   1   5   9   0
#y   2   6   10  1
#z   3   7   11  2

如果赋值给一个 Series, 则会精准匹配对应索引的数值, 若 Series 缺失 DataFrame 某些索引,则对应位置为空

df5['d'] = pd.Series([2,5,9],index = ['y','z','a'])
df5

image

增删数据

找出df中A列值为100的所有数据

1 df[df.A==100]
#     A    B    C
# 0    100    a    1

保留想要的列或删除指定列

保留想要的列

# 方法1:
df=df.loc[:,[‘name1’,‘name2’,‘name3’]]
# 方法2:
df2=df[[‘name1’,‘name2’,‘name3’]]

删除指定列

# 方法1:指定列名删除
df.drop([‘name1’,‘name2’],axis=1,inplace=True)
# 方法2:指定列数删除
df.drop(df.columns[0:n], axis=1, inplace=True)

修改行标签和列标签

修改列名
问题:
有一个DataFrame,列名为:['\(a', '\)b', '\(c', '\)d', '$e']
现需要改为:['a', 'b', 'c', 'd', 'e']

import pandas as pd
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

解决:

方式一:columns属性

# ①暴力
df.columns = ['a', 'b', 'c', 'd', 'e']

# ②修改
df.columns = df.columns.str.strip('$')

# ③修改
df.columns = df.columns.map(lambda x:x[1:])

方式二:rename方法、columns参数

# ④暴力(好处:也可只修改特定的列)
df.rename(columns=('$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}, inplace=True) 

# ⑤修改
df.rename(columns=lambda x:x.replace('$',''), inplace=True)

获取列名列表

DataFrame.columns.values.tolist()

常用方法

reindex()

表示重新索引,如果某个索引值当前不存在,就会引入
缺失值;可以通过fill_value参数填充默认值,也可以通过method参数设置填充方法;
reindex方法的methon参数的选项:
ffill或pad 前向填充值
bfill或backfill 后向填充值
或者是fill_value直接指定缺失值为多少

汇总,计算和描述性统计

Pandas 拥有一套常用的数学和统计方法, 但都是基于没有缺失数据的假设而构建的。
image

常用方法

读取excel表中的多个sheet

对于导入xlsx,pandas默认只导入第一个sheet,如果想导入多个/其他sheet需要指定:

# 按照index读取,1代表第二张表,默认是0 即默认只读取第一张表
>>> df = pd.read_excel(r'D:\myExcel/1.xlsx', sheet_name=1)
>>> df
  name  Chinese
0   lc       78
1   lb       79

# 按照表名读取
>>> df = pd.read_excel(r'D:\myExcel/1.xlsx', sheet_name='Sheet2')
>>> df
  name  Chinese
0   lc       78
1   lb       79


# 同时读取两张表,输入参数为列表
# 返回的是一个有序字典
>>> dfs = pd.read_excel(r'D:\myExcel/1.xlsx', sheet_name=[0, 'Sheet3'])
>>> dfs
OrderedDict([(0,      name  math  science
0     bob    23       12
1  millor    32       32
2   jiken    61       89
3     tom    34       94
4    json    83       12
5    dela    96       67
6   rison    90       34), ('Sheet3',   name  English
0   ld       32
1   by       98)])

找到缺失值的位置

问题描述:
判断缺失值一般采用 isnull(),然而生成的却是所有数据的true/false矩阵,对于庞大的数据dataframe,很难一眼看出来哪个数据缺失,一共有多少个缺失数据,缺失数据的位置。

首先对于存在缺失值的数据,如下所示

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10,6))
# Make a few areas have NaN values
df.iloc[1:3,1] = np.nan
df.iloc[5,3] = np.nan
df.iloc[7:9,5] = np.nan

#             0         1         2         3         4         5
#    0  0.520113  0.884000  1.260966 -0.236597  0.312972 -0.196281
#    1 -0.837552       NaN  0.143017  0.862355  0.346550  0.842952
#    2 -0.452595       NaN -0.420790  0.456215  1.203459  0.527425
#    3  0.317503 -0.917042  1.780938 -1.584102  0.432745  0.389797
#    4 -0.722852  1.704820 -0.113821 -1.466458  0.083002  0.011722
#    5 -0.622851 -0.251935 -1.498837       NaN  1.098323  0.273814
#    6  0.329585  0.075312 -0.690209 -3.807924  0.489317 -0.841368
#    7 -1.123433 -1.187496  1.868894 -2.046456 -0.949718       NaN
#    8  1.133880 -0.110447  0.050385 -1.158387  0.188222       NaN
#    9 -0.513741  1.196259  0.704537  0.982395 -0.585040 -1.693810

df.isnull()

df.isnull()会产生如下结果

       0      1      2      3      4      5
0  False  False  False  False  False  False
1  False   True  False  False  False  False
2  False   True  False  False  False  False
3  False  False  False  False  False  False
4  False  False  False  False  False  False
5  False  False  False   True  False  False
6  False  False  False  False  False  False
7  False  False  False  False  False   True
8  False  False  False  False  False   True
9  False  False  False  False  False  False

判断哪些”列”存在缺失值

df.isnull().any()则会判断哪些”列”存在缺失值

0    False
1     True
2    False
3     True
4    False
5     True
dtype: bool

只显示存在缺失值的行列

df[df.isnull().values==True]可以只显示存在缺失值的行列,清楚的确定缺失值的位置。

df[df.isnull().values==True]

#    Out[126]: 
#              0         1         2         3         4         5
#    1  1.090872       NaN -0.287612 -0.239234 -0.589897  1.849413
#    2 -1.384721       NaN -0.158293  0.011798 -0.564906 -0.607121
#    5 -0.477590 -2.696239  0.312837       NaN  0.404196 -0.797050
#    7  0.369665 -0.268898 -0.344523 -0.094436  0.214753       NaN
#    8 -0.114483 -0.842322  0.164269 -0.812866 -0.601757       NaN

日期数据的处理

日期数据转化

对于转成int常常除以\(10^9\)

# string to datetime
df['date'] = pd.to_datetime(df['date'])
# datetime  to int
pd.to_datetime('1970-01-01').value// 10 ** 9
# 整列datetime  to int
df['date'] = df['date'].apply(lambda x: x.value)// 10 ** 9
df['time'] = (df['time']* 10 ** 9).apply(pd.Timestamp)

按日期筛选数据

按年度获取数据

    print('---------获取2013年的数据-----------')
    print(df['2013'].head(2)) # 获取2013年的数据
    print(df['2013'].tail(2)) # 获取2013年的数据


    ---------获取2013年的数据-----------
                number
    date
    2013-10-24       3
    2013-10-25       4
                number
    date
    2013-12-27       2
    2013-12-30       2

获取2016至2017年的数据

    print('---------获取2016至2017年的数据-----------')
    print(df['2016':'2017'].head(2))  #获取2016至2017年的数据
    print(df['2016':'2017'].tail(2))  #获取2016至2017年的数据
    

    ---------获取2016至2017年的数据-----------
                number
    date              
    2016-01-04       4
    2016-01-07       6
                number
    date              
    2017-02-14       6
    2017-02-22       6

获取某月的数据

    print('---------获取某月的数据-----------')
    print(df['2013-11']) # 获取某月的数据
    

    ---------获取某月的数据-----------
                number
    date              
    2013-11-04       1
    2013-11-06       3
    2013-11-08       1
    2013-11-12       5
    2013-11-14       2
    2013-11-25       1
    2013-11-29       1

获取具体某天的数据

*   请注意dataframe类型的数据,获取具体某天的数据时,跟series是有些差异的,详细情况如下述代码所示:

    # 按日期筛选数据
    print('---------获取具体某天的数据-----------')
    # 获取具体某天的数据
    print(s['2013-11-06'])
    
    # 获取具体某天的数据,用datafrme直接选取某天时会报错,而series的数据就没有问题
    # print(df['2013-11-06'])
    
    #可以考虑用区间来获取某天的数据
    print(df['2013-11-06':'2013-11-06'])
    

    ---------获取具体某天的数据-----------
    3
                number
    date              
    2013-11-06       3


*   dataframe的truncate函数可以获取某个时期之前或之后的数据,或者某个时间区间的数据
*   但一般建议直接用切片(slice),这样更为直观,方便

    # dataframe的truncate函数可以获取某个时期之前或之后的数据,或者某个时间区间的数据
    # 但一般建议直接用切片(slice),这样更为直观,方便
    print('---------获取某个时期之前或之后的数据-----------')
    print('--------after------------')
    print(df.truncate(after = '2013-11'))
    print('--------before------------')
    print(df.truncate(before='2017-02'))
    

    ---------获取某个时期之前或之后的数据-----------
    --------after------------
                number
    date              
    2013-10-24       3
    2013-10-25       4
    2013-10-29       2
    2013-10-30       1
    --------before------------
                number
    date              
    2017-02-07       8
    2017-02-14       6
    2017-02-22       6

按日期显示数据

to_period()方法

  • 请注意df.index的数据类型是DatetimeIndex;
  • df_peirod的数据类型是PeriodIndex

按月显示,但不统计

    df_period = df.to_period('M') #按月显示,但不统计
    print(type(df_period))
    
    print(type(df_period.index))
    # 请注意df.index的数据类型是DatetimeIndex;
    # df_peirod的数据类型是PeriodIndex
    
    print(df_period.head())
    

    <class 'pandas.core.frame.DataFrame'>
    <class 'pandas.tseries.period.PeriodIndex'>
             number
    date           
    2013-10       3
    2013-10       4
    2013-10       2
    2013-10       1
    2013-11       1

按季度显示,但不统计

    print(df.to_period('Q').head()) #按季度显示,但不统计
    

            number
    date          
    2013Q4       3
    2013Q4       4
    2013Q4       2
    2013Q4       1
    2013Q4       1

按年度显示,但不统计

    print(df.to_period('A').head()) #按年度显示,但不统计
    

          number
    date
    2013       3
    2013       4
    2013       2
    2013       1
    2013       1

asfreq()方法

按年度频率显示

    df_period.index.asfreq('A') # 'A'默认是'A-DEC',其他如'A-JAN'
    

    PeriodIndex(['2013', '2013', '2013', '2013', '2013', '2013', '2013', '2013',
                 '2013', '2013',
                 ...
                 '2017', '2017', '2017', '2017', '2017', '2017', '2017', '2017',
                 '2017', '2017'],
                dtype='period[A-DEC]', name='date', length=425, freq='A-DEC')
    

    df_period.index.asfreq('A-JAN') # 'A'默认是'A-DEC',其他如'A-JAN'
    

    PeriodIndex(['2014', '2014', '2014', '2014', '2014', '2014', '2014', '2014',
                 '2014', '2014',
                 ...
                 '2017', '2017', '2017', '2017', '2017', '2017', '2017', '2018',
                 '2018', '2018'],
                dtype='period[A-JAN]', name='date', length=425, freq='A-JAN')
  • 按年度频率在不同情形下的显示,可参考下图所示:

按季度频率显示

    df_period.index.asfreq('Q') # 'Q'默认是'Q-DEC',其他如“Q-SEP”,“Q-FEB”
    

    PeriodIndex(['2013Q4', '2013Q4', '2013Q4', '2013Q4', '2013Q4', '2013Q4',
                 '2013Q4', '2013Q4', '2013Q4', '2013Q4',
                 ...
                 '2017Q1', '2017Q1', '2017Q1', '2017Q1', '2017Q1', '2017Q1',
                 '2017Q1', '2017Q1', '2017Q1', '2017Q1'],
                dtype='period[Q-DEC]', name='date', length=425, freq='Q-DEC')
    

    df_period.index.asfreq('Q-SEP') # 可以显示不同的季度财年,“Q-SEP”,“Q-FEB”
    # df_period.index = df_period.index.asfreq('Q-DEC') # 可以显示不同的季度财年,“Q-SEP”,“Q-FEB”
    # print(df_period.head())
    

    PeriodIndex(['2014Q1', '2014Q1', '2014Q1', '2014Q1', '2014Q1', '2014Q1',
                 '2014Q1', '2014Q1', '2014Q1', '2014Q1',
                 ...
                 '2017Q2', '2017Q2', '2017Q2', '2017Q2', '2017Q2', '2017Q2',
                 '2017Q2', '2017Q2', '2017Q2', '2017Q2'],
                dtype='period[Q-SEP]', name='date', length=425, freq='Q-SEP')
  • 按季度频率在不同情形下的显示,可参考下图所示:

按月度频率显示

    df_period.index.asfreq('M') # 按月份显示
    

    PeriodIndex(['2013-10', '2013-10', '2013-10', '2013-10', '2013-11', '2013-11',
                 '2013-11', '2013-11', '2013-11', '2013-11',
                 ...
                 '2017-01', '2017-01', '2017-01', '2017-01', '2017-01', '2017-01',
                 '2017-01', '2017-02', '2017-02', '2017-02'],
                dtype='period[M]', name='date', length=425, freq='M')

按工作日显示

  • method 1
    df_period.index.asfreq('B', how='start') # 按工作日期显示
    

    PeriodIndex(['2013-10-01', '2013-10-01', '2013-10-01', '2013-10-01',
                 '2013-11-01', '2013-11-01', '2013-11-01', '2013-11-01',
                 '2013-11-01', '2013-11-01',
                 ...
                 '2017-01-02', '2017-01-02', '2017-01-02', '2017-01-02',
                 '2017-01-02', '2017-01-02', '2017-01-02', '2017-02-01',
                 '2017-02-01', '2017-02-01'],
                dtype='period[B]', name='date', length=425, freq='B')
  • method 2
    df_period.index.asfreq('B', how='end') # 按工作日期显示
    

    PeriodIndex(['2013-10-31', '2013-10-31', '2013-10-31', '2013-10-31',
                 '2013-11-29', '2013-11-29', '2013-11-29', '2013-11-29',
                 '2013-11-29', '2013-11-29',
                 ...
                 '2017-01-31', '2017-01-31', '2017-01-31', '2017-01-31',
                 '2017-01-31', '2017-01-31', '2017-01-31', '2017-02-28',
                 '2017-02-28', '2017-02-28'],
                dtype='period[B]', name='date', length=425, freq='B')

按日期统计数据

按日期统计数据

按周统计数据

    print(df.resample('w').sum().head())
    # “w”,week
    

                number
    date              
    2013-10-27     7.0
    2013-11-03     3.0
    2013-11-10     5.0
    2013-11-17     7.0
    2013-11-24     NaN

按月统计数据

    print(df.resample('M').sum().head())
    # "MS"是每个月第一天为开始日期, "M"是每个月最后一天
    

                number
    date              
    2013-10-31      10
    2013-11-30      14
    2013-12-31      27
    2014-01-31      16
    2014-02-28       4

按季度统计数据

    print(df.resample('Q').sum().head())
    # "QS"是每个季度第一天为开始日期, "Q"是每个季度最后一天
    

                number
    date              
    2013-12-31      51
    2014-03-31      73
    2014-06-30      96
    2014-09-30     136
    2014-12-31     148
    

按年统计数据

    print(df.resample('AS').sum())
    # "AS"是每年第一天为开始日期, "A是每年最后一天
    

                number
    date              
    2013-01-01      51
    2014-01-01     453
    2015-01-01     743
    2016-01-01    1552
    2017-01-01      92
    
  • 关于日期的类型,按参考下图所示来选择合适的分期频率:

按日期统计后,按年或季度或月份显示

按年统计并显示

    print(df.resample('AS').sum().to_period('A'))
    # 按年统计并显示
    

          number
    date        
    2013      51
    2014     453
    2015     743
    2016    1552
    2017      92
    

按季度统计并显示

    print(df.resample('Q').sum().to_period('Q').head())
    # 按季度统计并显示
    

            number
    date          
    2013Q4      51
    2014Q1      73
    2014Q2      96
    2014Q3     136
    2014Q4     148
    

按月度统计并显示

    print(df.resample('M').sum().to_period('M').head())
    # 按月度统计并显示
    

             number
    date           
    2013-10      10
    2013-11      14
    2013-12      27
    2014-01      16
    2014-02       4

按日期和其他条件组合分组

要按日期和其他条件组合分组,可以使用 Pandas 的 groupby 方法。具体来说,

  1. 首先使用 set_index 按照日期将 DataFrame 转换为时间序列格式,
  2. 再使用 groupby 按照其他条件进行分组。

以一个包含日期、城市和销售额的示例数据集为例:

import pandas as pd

data = {
    'date': ['2022-01-01', '2022-01-01', '2022-01-02', '2022-01-02'],
    'city': ['Shanghai', 'Beijing', 'Shanghai', 'Beijing'],
    'sales': [1000, 2000, 1500, 2500]
}

df = pd.DataFrame(data)
df['date'] = pd.to_datetime(df['date'])

现在我们可以使用 set_index 将 date 列设置为索引,从而转换为时间序列格式:

df = df.set_index('date')

此时 df 的索引变成了日期类型。接下来,我们可以使用 groupby 方法按照 city 和日期进行分组:

grouped = df.groupby([pd.Grouper(freq='D'),'city'])

这里 [pd.Grouper(freq='D'),'city'] 表示按照天为频率(日历日),并按照城市进行分组。现在,我们可以对分组后的数据进行聚合操作,如求和等:

result = grouped.sum()

这样,我们就可以得到按照日期和城市进行分组后的销售额总和。

DataFrame 新增列的五种方法

分组和统计个数

根据不同列分组,分组后对不同列使用不同的聚合函数

对所有列求和,求平均,统计

import pandas as pd
student = pd.read_excel(".../Students.xlsx",index_col="ID")
temp = student[["Test_1","Test_2","Test_3"]]
student["total"] = temp.sum(axis=1)#axis 0为列,1为行
student["avg"] = temp.mean(axis=1)
print(student)

注意: 该操作自动忽略了空值进行均值

案例

【例】与书本不同,本节利用tushare读取招商银行股票数据,并进行 Pandas 基本操作。tushare为金融数据分析提供便捷、快速的接口,与投研和量化策略无缝对接 数据丰富 拥有丰富的数据内容,如股票、基金、期货、数字货币等行情数据,公司财务、基金经理等基本面数据。tushare是第三方库,因此,在首次使用时,需要通过pip安装。

import pandas as pd
import tushare as ts
import datetime
ZSYH = ts.get_hist_data('600036', '2020-08-31', '2020-09-11')
ZSYH.head(3)

image

ZSYH.tail(3)

image

posted @ 2023-04-04 10:28  kingwzun  阅读(103)  评论(0编辑  收藏  举报