pandas数据分析实例--以电票数据为例

有这样一张电票数据表:2020转贴现清单.csv (实际68行数据,含标题行)

今天我们用它来练习用python (含 Pandas, pymysql)和 MySQL 如何对它进行一些基础的操作.

导入数据
首先, 我们导入它

import pandas as pd
#本开关用于控制pandas中float数据的显示方式,关闭科学计数方式,显示小数点后两位.
pd.options.display.float_format='{:.2f}'.format
#表1是清单,表2是承兑行额度表
file1_path = 'C:/Users/Desktop/PY/2020转贴现清单.csv'
file2_path = 'C:/Users/Desktop/PY/剩余额度.csv'
#用read_csv读取,只取四列usecols("票号", "票面金额(元)","票面到期日","承兑行"),注意cols从0开始数.
bill_list = pd.read_csv(file1_path, usecols=(0,4,9,17),header=0)

其它的导入方式还有:

• pd.read_csv(filename_path):从CSV文件导入数据
• pd.read_table(filename_path):从限定分隔符的文本文件导入数据
• pd.read_excel(filename_path):从Excel文件导入数据
• pd.read_sql(query, connection_object):从SQL表/库导入数据
• pd.read_json(json_string):从JSON格式的字符串导入数据
• pd.read_html(url):解析URL、字符串或者HTML文件,抽取其中的tables表格
• pd.read_clipboard():从你的粘贴板获取内容,并传给read_table()
• pd.DataFrame(dict):从字典对象导入数据,Key是列名,Value是数据

得到的bill_list如下图:
bill_list

Out[7]: 
                              票据号码       票面金额         到期日     承兑行
0   130558100301420200703673063725 2000000.00  2020-11-01  中国民生银行
1   110329007403220200618660897195 1000000.00  2020-11-02  中国农业银行
2   110329007403220200618660897218 1000000.00  2020-11-02  中国农业银行
3   110429000615420200619662041630 1000000.00  2020-11-02    中国银行
4   130558401822120200804695066745 8000000.00  2020-11-02  中国民生银行
..                             ...        ...         ...     ...
63  110458602041820200528647586166 1500000.00  2020-11-28    中国银行
64  130133100013120200527645905735 1000000.00  2020-11-28    交通银行
65  130133100013120200527645905743 1000000.00  2020-11-28    交通银行
66  130558100301420200730692349173 2000000.00  2020-11-28  中国民生银行
67  130558506700420200630670941661 1455514.85  2020-12-30  中国民生银行

[68 rows x 4 columns]

bill_list是一个DataFrame, 大小是[68 rows x 4 columns], 下面我们再对它进行一些操作, 注意体会各个命令的实际效果

**查看DataFrame的信息**

list(bill_list)
Out[6]: ['票据号码', '票面金额', '到期日', '承兑行']

bill_list.columns
Out[8]: Index(['票据号码', '票面金额', '到期日', '承兑行'], dtype='object')

bill_list.values

Out[3]: 
array([['130558100301420200703673063725', 2000000.0, '2020-11-01', '中国民生银行'],
       ['110329007403220200618660897195', 1000000.0, '2020-11-02', '中国农业银行'],
       ['110329007403220200618660897218', 1000000.0, '2020-11-02', '中国农业银行'],
       ['110429000615420200619662041630', 1000000.0, '2020-11-02', '中国银行'],
       ['130558401822120200804695066745', 8000000.0, '2020-11-02', '中国民生银行'],
       ['130558100301420200804694990785', 2273800.0, '2020-11-03', '中国民生银行'],
       ['130558506700420200630670941661', 1455514.85, '2020-12-30','中国民生银行']], dtype=object)

关于df.values, dtype=object, 它大概是这么个意思

其它的操作还有:

• df.head(n):查看DataFrame对象的前n行(不加参数,默认前10行)
• df.tail(n):查看DataFrame对象的最后n行(不加参数,默认后10行)
• df.shape():查看行数和列数(维度查看)
• df.info():查看索引、数据类型和内存信息
• df.describe():查看数值型列的汇总统计
• s.value_counts(dropna=False):查看Series对象的唯一值和计数
• df.apply(pd.Series.value_counts):查看DataFrame对象中每一列的唯一值和计数
• df.dtypes:查看每一列的数据类型(扩展:df['two'].dtypes,查看“two”列的类型)
• df.isnull():查看空置(注:空置部分会用true显示,不是空置False显示)(扩展:df['two'].isnull,查看“two”这一列的空置)
• df.values:查看数据表的值
• df.columns:查看列名称

数据排序

按票据号码升序排列, axis =0 是按列, 也可以不写,默认. 如果 axis = 1, 就是按行, 就必须写.
bill_list.sort_values(by='票据号码',axis =0)

Out[9]: 
                              票据号码       票面金额         到期日     承兑行
12  110258100201120200310594392608 6300000.00  2020-11-10  中国工商银行
24  110258650027020200515637250023 2900000.00  2020-11-15  中国工商银行
42  110258800287820200820704406617 1550000.00  2020-11-20  中国工商银行
52  110258800287820200825707679003 2250000.00  2020-11-25  中国工商银行
59  110258800287820200827710725997 1200000.00  2020-11-27  中国工商银行
..                             ...        ...         ...     ...
35  190729000121820200724687172545 2000000.00  2020-11-19  中国农业银行
36  190729000121820200724687172762 2000000.00  2020-11-19  中国农业银行
37  190729000121820200724687172779 2000000.00  2020-11-19  中国农业银行
38  190729000121820200724687182977 2000000.00  2020-11-19  中国农业银行
39  190729000121820200724687182985 2000000.00  2020-11-19  中国农业银行

[68 rows x 4 columns]

如果想排序的有两列,比如按'票面金额'倒序(由大到小),按'到期日'顺序(由小到大),可以这么写:
bill_list.sort_values(by=['票面金额','到期日'],axis =0,ascending = [False, True])

Out[10]: 
                              票据号码        票面金额         到期日       承兑行
32  131022100018820200518638790084 35060806.35  2020-11-18  上海浦东发展银行
18  131060200017220200515637681036 30428000.00  2020-11-13  上海浦东发展银行
19  131022100018820200513636202745 30000000.00  2020-11-13  上海浦东发展银行
13  130133700007220200511633966401 12000000.00  2020-11-11      交通银行
4   130558401822120200804695066745  8000000.00  2020-11-02    中国民生银行
..                             ...         ...         ...       ...
3   110429000615420200619662041630  1000000.00  2020-11-02      中国银行
25  130158100008620200515637990749  1000000.00  2020-11-15      交通银行
44  130558506700420200520640035647  1000000.00  2020-11-20    中国民生银行
64  130133100013120200527645905735  1000000.00  2020-11-28      交通银行
65  130133100013120200527645905743  1000000.00  2020-11-28      交通银行

[68 rows x 4 columns]

数据切片
所谓切片, 其实就是按照一定的条件选择你想要数据

• df.isin([5]):判断全部数据值中是否有5
• dr[col].isin([5]):判断列col中是否有5
• df[col]:根据列名,并以Series的形式返回列
• df[[col1, col2]]:以DataFrame形式返回多列
• s.iloc[0]:按位置选取行数据
• s.loc['index_one']:按索引选取行数据
• df.iloc[0,:]:返回第一行
• df.iloc[0,0]:返回第一列的第一个元素
• df.ix[0] 或 df.ix[raw] :ix函数可以根据行位置或行标签选择行数据

注:loc函数根据行标签进行行选择;
iloc函数根据行位置进行行选择;
ix函数可以根据行位置选择也可以根据行标签选择。

今天我们用df.isin(), 它是这样使用的df[col].isin(list), 用来查看某一列col中包含list的记录, 它会返回一列布尔值, 如果你要提取这样切片的结果,你得用:df[df[col].isin(list)]
比如:
查询'承兑行'一列中包含'中国民生银行'的记录:

xyz = bill_list1['承兑行'].isin(['中国民生银行'])
xyz
Out[13]: 
票据号码
130558100301420200703673063725     True
110329007403220200618660897195    False
110329007403220200618660897218    False
110429000615420200619662041630    False
130558401822120200804695066745     True
 
110458602041820200528647586166    False
130133100013120200527645905735    False
130133100013120200527645905743    False
130558100301420200730692349173     True
130558506700420200630670941661     True
Name: 承兑行, Length: 68, dtype: bool

type(bill_list1['承兑行'].isin(['中国民生银行']))
Out[14]: pandas.core.series.Series

用这个结果, 再去和df组合一次,才能筛选出你想要的符合条件的记录:
bill_list1[bill_list1['承兑行'].isin(['中国民生银行'])]

Out[15]: 
                                     票面金额         到期日     承兑行
票据号码                                                         
130558100301420200703673063725 2000000.00  2020-11-01  中国民生银行
130558401822120200804695066745 8000000.00  2020-11-02  中国民生银行
130558100301420200804694990785 2273800.00  2020-11-03  中国民生银行
130558100301420200706673782421 2000000.00  2020-11-04  中国民生银行
130558100301420200706673838648 2000000.00  2020-11-04  中国民生银行
130558100301420200709676161852 2000000.00  2020-11-07  中国民生银行
...

两个小TIPS

  1. 由于columns的文字中可能含有空格,不当引用时会报KeyError错误, 影响后面的引用, 为了消除这个影响,我们要对它进行处理
    例如, 通过构建函数,来自动净化Dataframe的columns,仅仅只是columns,别的不行
def columns_strip(df_name):
    columns=list(df_name.columns)
    columns_new =[i.strip() for i in columns]
    df_name.columns = columns_new

columns_strip(bill_list)        #去除columns里的空格
  1. 下面这段代码将Series中的带千分位的数字(其实是str)去掉千分符再换为数字float,注意,要以索引为操作对象.
    不转换会遇到类似的报错: ValueError: could not convert string to float: '2,000,000.00'
bill_amount=bill_list['票面金额']       #pandas.core.series.Series
for i in bill_amount.index:
    bill_amount[i]=bill_amount[i].replace(',','')
    bill_amount[i]=float(bill_amount[i])

新生成的bill_amount还是pandas.core.series.Series, 但是要注意,这里修改好之后, bill_list里的票面金额也变了!!! 因为这个是对索引操作的
bill_amount[i]=float(bill_amount[i])也可以写成: s.astype(float):将Series中的数据类型更改为float类型

bill_list1 = bill_list.set_index('票据号码')    #单索引
#以.set_index([x,y])方式,设置双索引,用于约束条件,要把有重复的列放在前面
#bill_list2 = bill_list.set_index(['承兑行','票据号码'])    #双索引

bill_dict = bill_list1.to_dict('dict')
#bill_dict 是一个三个大字典套嵌的字典, 它包括:{{票号:票面金额},{票号:到期日},{票号:承兑行}}

bill_dict
Out[27]: 
{'票面金额': {'130558100301420200703673063725': 2000000.0,
  '110329007403220200618660897195': 1000000.0,
  '110329007403220200618660897218': 1000000.0,
  ...
  '130133100013120200527645905743': 1000000.0,
  '130558100301420200730692349173': 2000000.0,
  '130558506700420200630670941661': 1455514.85},
 '到期日': {'130558100301420200703673063725': '2020-11-01',
  '110329007403220200618660897195': '2020-11-02',
  '110329007403220200618660897218': '2020-11-02',
  ...
  '130133100013120200527645905743': '2020-11-28',
  '130558100301420200730692349173': '2020-11-28',
  '130558506700420200630670941661': '2020-12-30'},
 '承兑行': {'130558100301420200703673063725': '中国民生银行',
  '110329007403220200618660897195': '中国农业银行',
  '110329007403220200618660897218': '中国农业银行',
  '110429000615420200619662041630': '中国银行',
  '130558401822120200804695066745': '中国民生银行',
  ...
  '130133100013120200527645905743': '交通银行',
  '130558100301420200730692349173': '中国民生银行',
  '130558506700420200630670941661': '中国民生银行'}}

使用时,要分别先取三个大字典的键值对 :这三个字典都是以 "票号"为 key的

bill_dict_amount = bill_dict['票面金额']
bill_dict_maturity = bill_dict['到期日']
bill_dict_bank = bill_dict['承兑行']

bill_dict_amount
Out[28]: 
{'130558100301420200703673063725': 2000000.0,
 '110329007403220200618660897195': 1000000.0,
 '110429000615420200619662041630': 1000000.0,
...
 '130558100301420200730692349173': 2000000.0,
 '130558506700420200630670941661': 1455514.85}

bill_dict_bank
Out[29]: 
{'130558100301420200703673063725': '中国民生银行',
 '110329007403220200618660897195': '中国农业银行',
 '110329007403220200618660897218': '中国农业银行',
 '110429000615420200619662041630': '中国银行',
 ...
 '130558100301420200730692349173': '中国民生银行',
 '130558506700420200630670941661': '中国民生银行'}

之所以设置成这样,是因为票据号码是唯一的,用它做了index对于以后的引用和线性运算会有很大的方便.

原文地址:https://www.cnblogs.com/treasury-manager/p/13857464.html