(博文体系参考:《Python数据分析与应用》课本)
任务数据如下:
读入csv文件时,encoding必须是正确的,常用的编码格式有:UTF-8 , UTF-16 , GBK , GB2312 , GB18030等。
如果和文件的编码格式不符合时,则会报错:
import pandas as pdpath = "D:/mystudy/大三上学期作业/PythonPython/chapter4/第4章任务数据/data/meal_order_info.csv"
order1 = pd.read_csv(path,sep=',',encoding = 'utf-8') # 默认格式就是utf-8报错:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc3 in position 0: invalid continuation byte
比较读入文件的sep参数不同时,读入文件的不同:
order1 = pd.read_csv(path,sep=',',encoding = 'gbk')order2 = pd.read_csv(path,sep=';',encoding = 'gbk')order3 = pd.read_csv(path,sep='"',encoding = 'gbk')
可以用os库中的os.listdir()函数来查看当前文件夹下的所有文件:
import os
print(os.listdir())
type(os.listdir())输出:
['meal_order_detail.xlsx','meal_order_detail1.sql','meal_order_detail2.sql','meal_order_detail3.sql','meal_order_info.csv','test.py','users.xlsx','数据特征说明.xlsx']list
查看当前目录的子文件夹下的文件目录:(假设现在在“第四章任务数据”子文件夹下,绝对目录认为是本博文第一段代码中的path路径)
os.listdir('../data/')输出:(未实际运行,但理论上是这样?)
['meal_order_detail.xlsx','meal_order_detail1.sql','meal_order_detail2.sql','meal_order_detail3.sql','meal_order_info.csv','test.py','users.xlsx','数据特征说明.xlsx']
可以将数据以csv文件格式或者是xls文件格式(也就是Excel对应的)保存到本地。
关于pandas的重要部分:DataFrame
注意取元素的时候,尽量用index,而不是直接取行,因为数据可能被改变过了。
我们先来看一下order1读入的具体内容,并且查看一下order1的类型:
注意到,最左侧的列一定是行的索引,索引为0的行是标题(用.column获取),
注意:不论是DataFrame还是Series,访问索引的唯一方法只有: .index,没法用loc或者其他方法获取到!!!
print("查看order1的主要参数:")
print("values:")
print(order1.values)
print("index:")
print(order1.index)
print("columns:")
print(order1.columns)
print("dtypes:")
print(order1.dtypes)输出:查看order1的主要参数:
values:
[[417 1442 4 ... 1 18688880641 '苗宇怡'][301 1095 3 ... 1 18688880174 '赵颖'][413 1147 6 ... 1 18688880276 '徐毅凡']...[692 1155 8 ... 1 18688880327 '习一冰'][647 1094 4 ... 1 18688880207 '章春华'][570 1113 8 ... 1 18688880313 '唐雅嘉']]
index:
RangeIndex(start=0, stop=945, step=1)
columns:
Index(['info_id', 'emp_id', 'number_consumers', 'mode', 'dining_table_id','dining_table_name', 'expenditure', 'dishes_count', 'accounts_payable','use_start_time', 'check_closed', 'lock_time', 'cashier_id', 'pc_id','order_number', 'org_id', 'print_doc_bill_num', 'lock_table_info','order_status', 'phone', 'name'],dtype='object')
dtypes:
info_id int64
emp_id int64
number_consumers int64
mode float64
dining_table_id int64
dining_table_name int64
expenditure int64
dishes_count int64
accounts_payable int64
use_start_time object
check_closed float64
lock_time object
cashier_id float64
pc_id float64
order_number float64
org_id int64
print_doc_bill_num float64
lock_table_info float64
order_status int64
phone int64
name object
dtype: object
.
注意,DataFrame可以转置!
有了转置操作的加持,许多需求就变得简单了。
.
注意,DataFrame可以做运算!(比如乘法运算)
输入:(注意!两个int类型的Series是可以做乘法的!)
order1['info_id']*order1['emp_id']Out[87]:
0 601314
1 329595
2 473711
3 483890
4 428848940 701895
941 731808
942 799260
943 707818
944 634410
Length: 945, dtype: int64
.
1.查看DataFrame中数据
使用命令:
order1['info_id'] # 当成字典去访问,要加单引号或:order1.info_id # 当成dataframe中的属性去访问,不需要加单引号输出:0 417
1 301
2 413
3 415
4 392...
940 641
941 672
942 692
943 647
944 570
Name: info_id, Length: 945, dtype: int64虽然都可以访问,但是推荐第一种,因为避免和关键字重名或是列名为'123'这样的数字字符串等,容易引起混淆
注意,将DataFrame转置后,则不能这样用上述方法数据了!
下面来学习取出一列,多列,所有列的元素。
但是要注意一个区别,这里的第一个中括号代表的不是行索引!!而是属性列!
想要访问索引的唯一方法就是调用.index函数!
同时还有两个函数送上:.head(x),.tail(x) ,分别用来访问前x个,后x个。(不传参数则默认为5)
当然,还有访问操作更加灵活的.loc[]和.iloc[]函数(注意是中括号!!!这个后面再说)
请取出‘info_id’这一个Series中的前三个元素
输入:
order1['info_id'][0:3]Out[43]:
0 417
1 301
2 413
Name: info_id, dtype: int64输入:
order1['info_id'].shapeOut[45]: (945,)输入:
type(order1['info_id'])Out[46]: pandas.core.series.Series
请取出'info_id'和'emp_id'这两列的前三个元素:
输入:
order1[['info_id','emp_id']].shape #注意别忘了里面这一层中括号!他需要传入一个listOut[48]: (945, 2)输入:
order1[['info_id','emp_id']][0:3]Out[49]: info_id emp_id
0 417 1442
1 301 1095
2 413 1147输入
order1[['info_id','emp_id']].head(3) #不传参数则默认为5列Out[53]: info_id emp_id
0 417 1442
1 301 1095
2 413 1147
取出所有列的前三个元素:
输入:
order1[:][0:3]Out[50]: info_id emp_id number_consumers ... order_status phone name
0 417 1442 4 ... 1 18688880641 苗宇怡
1 301 1095 3 ... 1 18688880174 赵颖
2 413 1147 6 ... 1 18688880276 徐毅凡[3 rows x 21 columns]输入:
order1[:][0:3].shapeOut[51]: (3, 21)
下面来介绍兄弟函数loc[]和iloc[]函数(其实就是和array几乎一样的多维访问方式了),这两个函数的区别仅在对参数的要求有部分区别。(当然,也有交叉重叠的部分)
注意:loc[]函数传入的行索引是前闭后闭区间,iloc[]函数传入的行索引和列索引都是前闭后开
报错系列:
order1.iloc[0:3,'info_id']order1.loc[0:3,0:3]无错系列:
order1.loc[0:3,'info_id']order1.loc[0:3,:]order1.iloc[0:3,0:3]order1.iloc[0:3,:]例子:
(前两个例子的输出一致)输入1:
order1.iloc[0:3,[0,1,2]]Out[65]: info_id emp_id number_consumers
0 417 1442 4
1 301 1095 3
2 413 1147 6输入2:
order1.iloc[0:3,0:3]Out[62]: info_id emp_id number_consumers
0 417 1442 4
1 301 1095 3
2 413 1147 6输入3:(我也不知道为啥标签变成行了....求大佬告知)
order1.iloc[3,[0,1,2]]Out[66]:
info_id 415
emp_id 1166
number_consumers 4
Name: 3, dtype: object输入4:(loc极其灵活,第一维可以传入表达式来筛选行,就和数据库的select语句一样灵活!iloc却不行,根本原因在于表达式语句返回一个bool类型的Series,而iloc可接收的数据类型不包括Series!但非要使用iloc也是可以的,比较麻烦,在返回的Series中取其value,让他变成一个bool类型的array即可。)
order1.loc[order1['number_consumers']==5,['number_consumers','info_id']]Out[72]: number_consumers info_id
38 5 688
43 5 317
71 5 831
97 5 266
126 5 712
.. ... ...
852 5 1017
858 5 1025
870 5 1104
896 5 1300
911 5 588[71 rows x 2 columns]
其实还有一种ix[]方法,但是效率低于loc和iloc,所以在此不做介绍。
2.修改DataFrame中数据
注意修改前先备份原文件!order2 = order1.copy()
尽量使用loc[]或者iloc[]而不是用属性去访问,原因不详,反正会有warning(有懂的大神欢迎讨论区讨论)
(目前思考:原因和二维array中取数,不能直接[x][y]而应该[x , y]是一个道理,对于array:你直接[][]相当于对得到的第一个一维数组再去取值,所以速度会慢很多,而且这样不是标准写法。对于这里,warning表示的是你对一个slice的一个切片,相当于是一个临时变量副本?然后你再对他进行操作,所以他给了你一个提示?所以这样取数字的时候不会给你这个warning,但是当你改变值的时候,就给你这样一个警示,让你检查一下语法是否正确?所以对于DataFrame一般来说这样二维操作,取数没有问题,对于一维的运算也没有任何问题,可以任意使用,但是对于二维问题的赋值操作需要谨慎?所以一般还是用loc[]比较常见?以上仅时个人意见,不具有权威性。反正对于下面用到的order1['use_start_time'] = pd.to_datetime(order1['use_start_time'])这一句对一维的赋值操作,是不会有任何问题的,也就是说按照属性直接取值是可以的,但是对于[][]这样的二维切片操作就要注意了)
输入;
order1['info_id'][0] = 400警告:
__main__:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrameSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy输入:
order1.loc[0,'info_id'] = 417无警告
3.增添DataFrame中数据
新增一列:
输入1:(前面提到了,两个int类型的Series是可以做乘法的!)
order1['hahaha']=order1['info_id']*10
order1['hahaha']Out[84]:
0 4170
1 3010
2 4130
3 4150
4 3920940 6410
941 6720
942 6920
943 6470
944 5700
3.删除DataFrame中数据
输入1:(注意,可以一口气删多列)
order1.drop(labels=['order_status','lock_table_info'],axis=1) #当labels是列标的时候,axis=1Out[29]: info_id emp_id number_consumers ... print_doc_bill_num phone name
0 417 1442 4 ... NaN 18688880641 苗宇怡
1 301 1095 3 ... NaN 18688880174 赵颖
2 413 1147 6 ... NaN 18688880276 徐毅凡
3 415 1166 4 ... NaN 18688880231 张大鹏
4 392 1094 10 ... NaN 18688880173 孙熙凯
.. ... ... ... ... ... ... ...
940 641 1095 8 ... NaN 18688880307 李靖
941 672 1089 6 ... NaN 18688880305 莫言
942 692 1155 8 ... NaN 18688880327 习一冰
943 647 1094 4 ... NaN 18688880207 章春华
944 570 1113 8 ... NaN 18688880313 唐雅嘉[945 rows x 19 columns]输入2:(删除第0行)
order1.drop(labels=0,axis=0)Out[30]: info_id emp_id number_consumers ... order_status phone name
1 301 1095 3 ... 1 18688880174 赵颖
2 413 1147 6 ... 1 18688880276 徐毅凡
3 415 1166 4 ... 1 18688880231 张大鹏
4 392 1094 10 ... 1 18688880173 孙熙凯
5 381 1243 4 ... 1 18688880441 沈晓雯
.. ... ... ... ... ... ... ...
940 641 1095 8 ... 1 18688880307 李靖
941 672 1089 6 ... 1 18688880305 莫言
942 692 1155 8 ... 1 18688880327 习一冰
943 647 1094 4 ... 1 18688880207 章春华
944 570 1113 8 ... 1 18688880313 唐雅嘉[944 rows x 21 columns]
关于时间模块
将字符串时间转换成标准时间
注意那些有趣的函数都是来自datatime库的而不是numpy库!有兴趣的同学可以学一下datatime库!!
以上类型,概念上理解分成两类,一类代表时间点,一类代表时间段。
字符串转换成标准时间分成三类:
1.直接转化成Timestamp格式
将字符串转换成标准时间的代码十分简短,这里提供两种方式(其实本质上是一种,只不过一种是以属性形式去访问,另一种是loc[]去访问)
order1.loc[:,'lock_time'] = pd.to_datetime(order1.loc[:,'lock_time'])order1['use_start_time'] = pd.to_datetime(order1['use_start_time'])
Timestamp类型时间,代表时间点可以进行减法,比如用终止时间减去起始时间,取出那个min,如果这个min小于0,那么肯定是异常值了,也就是说这是处理异常值的一个方法。
2.直接转化成 DatatimeIndex类型
不常用,不介绍
3.直接转化成PeriodIndex类型
不常用,不介绍
提取时间序列数据信息
样例代码:
yy = [item.year for item in order1['lock_time']]输出会是一个list
加减时间数据,学习Timedelta类!
对于时间,可以做加法也可以做减法。但是作为Timestamp类型,一定要注意加完或减完的范围一定要在 1677-09-21 到 2262-04-11 之间
加减时间数据练习及加深理解:
在对话框中按照顺序输入下面代码:输入1:
df_Update['ListingInfo1']Out[74]:
0 2014-03-05
1 2014-03-05
2 2014-03-05
3 2014-03-05
4 2014-03-05372458 2014-03-05
372459 2014-03-05
372460 2014-03-05
372461 2014-03-05
372462 2014-03-05
Name: ListingInfo1, Length: 372463, dtype: timedelta64[ns]输入2:
df_Update['ListingInfo1'] = df_Update['ListingInfo1'] + pd.to_datetime('2014-03-05 11:22:33')报错输入3:
df_Update['ListingInfo1'] = df_Update['ListingInfo1'] - pd.to_datetime('2014-03-05 11:22:33')df_Update['ListingInfo1']
Out[77]:
0 -1 days +12:37:27
1 -1 days +12:37:27
2 -1 days +12:37:27
3 -1 days +12:37:27
4 -1 days +12:37:27372458 -1 days +12:37:27
372459 -1 days +12:37:27
372460 -1 days +12:37:27
372461 -1 days +12:37:27
372462 -1 days +12:37:27
Name: ListingInfo1, Length: 372463, dtype: timedelta64[ns]输入4:df_Update['ListingInfo1'] = df_Update['ListingInfo1'] + pd.to_datetime('2014-03-05 11:22:33')df_Update['ListingInfo1']Out[79]:
0 2014-03-05
1 2014-03-05
2 2014-03-05
3 2014-03-05
4 2014-03-05372458 2014-03-05
372459 2014-03-05
372460 2014-03-05
372461 2014-03-05
372462 2014-03-05
Name: ListingInfo1, Length: 372463, dtype: datetime64[ns]输入5:df_Update['ListingInfo1'] = df_Update['ListingInfo1'] + pd.Timedelta(seconds = 1)df_Update['ListingInfo1']Out[81]:
0 2014-03-05 00:00:01
1 2014-03-05 00:00:01
2 2014-03-05 00:00:01
3 2014-03-05 00:00:01
4 2014-03-05 00:00:01372458 2014-03-05 00:00:01
372459 2014-03-05 00:00:01
372460 2014-03-05 00:00:01
372461 2014-03-05 00:00:01
372462 2014-03-05 00:00:01
Name: ListingInfo1, Length: 372463, dtype: datetime64[ns]输入6:df_Update['ListingInfo1'][0] = df_Update['ListingInfo1'][0] - pd.Timedelta(seconds = 1)报warning:(但是依旧可以执行)
__main__:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrameSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy输入7:df_Update['ListingInfo1']Out[84]:
0 2014-03-04 23:59:59
1 2014-03-05 00:00:00
2 2014-03-05 00:00:00
3 2014-03-05 00:00:00
4 2014-03-05 00:00:00372458 2014-03-05 00:00:00
372459 2014-03-05 00:00:00
372460 2014-03-05 00:00:00
372461 2014-03-05 00:00:00
372462 2014-03-05 00:00:00
Name: ListingInfo1, Length: 372463, dtype: datetime64[ns]
对于求访问数据类型的几种方法:
要么就是直接用DataFrame的dtypes函数(别落下了s!!)
要么就是单独取出一个数据出来type()(或者直接输出,一般也会给出对应的类型)
但是为什么
会不一样?百思不得其解
答:可能是Console的原因吧,我print一下就好了
end