Series是线性的数据结构,带有标签的一维数组,轴标签统称为索引,数据和标签之间存在联系。
用series将以下三个数据存入s1中:105,130,116
import pandas as pd
s1=pd.Series([105,130,116])
print(s1)
我们会得到如下的 结果
0 105
1 130
2 116
dtype: int64
Series的索引可以通过代码来指定,并且可以使用字符串,将以上三个数据的索引分别指定为:‘语文’,‘数学’,‘英语’通过索引值‘数学’可以访问到数学成绩,也可以通过索引值来修改序列中的值
import pandas as pd
s1=pd.Series([105,130,116],index=['语文','数学','英语'])
print(s1)
结果如下
语文 105
数学 130
英语 116
dtype: int64
Series和列表的主要区别在于列表的元素索引是固定的0,1,2,3··· 而Series除了可以使用数字索引,还可以自定义索引。
表达式s1.index和s1.values分别代表序列的索引和值,可以使用循环结构遍历到,如下所示:
另外,除了使用列表来创建Series,还可以使用字典来创建:
import pandas as pd
s1 = pd.Series({"语文":105,"数学":130,"英语":116})
print(s1)
DataFrame对象是一个二维表格,由1个索引列(index)和若干个数据列组成。其中,每列中的元素类型必须一致,而不同的列可以拥有不同的元素类型。
import pandas as pd
data = {'姓名':['小王','小明','小红'],'语文':['105','103','96'],'数学':['130','132','145'],'英语':['106','98','93']}
df1 = pd.DataFrame(data,columns=["姓名","语文","数学",'英语'])
print(df1)
结果如下
姓名 语文 数学 英语
0 小王 105 130 106
1 小明 103 132 98
2 小红 96 145 93
其中的columns是设定df1中数据列的顺序的参数,输出结果会按照columns后面的顺序输出
接下来我以“超市销售数据.csv”这个文件进行演示
在读取文件前一定要确保存储数据的文件(如.csv文件)要和你编写程序的.py文件在同一目录下
一般我们用pandas读取.csv文件或.xlsx文件时使用read_csv( )或read_excel( )
注意!在用pandas的read_csv( )或read_excel( )函数读取含有中文路径的文件时,会出现解码问题,可以用open( )函数打开,如:pd.read_csv(open(中文路径))
读取并打印:
import pandas as pd
df=pd.read_csv(open("超市销售数据.csv"))
print(df)
收银员名称 单据号 销售时间 ... 销售单价 销售数量 销售金额
0 陈晨 20000001 20141018072043 ... 1.7 1.0 1.7
1 陈晨 20000002 20141018073215 ... 4.4 1.0 NaN
2 陈晨 20000003 20141018073519 ... 86.9 1.0 86.9
3 陈晨 20000004 20141018073544 ... 7.2 1.0 NaN
4 陈晨 20000005 20141018073612 ... 5.6 1.0 5.6
... ... ... ... ... ... ...
65530 刘珍霞 20031877 20150228184246 ... 2.9 1.0 2.9
65531 刘珍霞 20031877 20150228184246 ... 4.5 1.0 4.5
65532 刘珍霞 20031877 20150228184246 ... 1.5 2.0 3.0
65533 刘珍霞 20031878 20150228184336 ... 10.9 1.0 10.9
65534 刘珍霞 20031878 20150228184336 ... 1.5 2.0 3.0
[65535 rows x 8 columns]
第二行中缺失数据,可以用drop( )函数删除第二行
注意第二行的索引是1,所以我们在后面填入1就可以删除了,但是删除后得到的新二维表需要重新赋值给原先存放二维表的变量,有下面两种方法。
方法一
df=df.drop(1)
方法二
df.drop(1,inplace=True)
drop()函数默认是对行进行操作,如果需要对列操作需要增加参数axis=1
(axis用于指定二维表中的行或列,drop()函数中若不写该参数默认为0指定行,1则表示指定列)
拓展:dropna()函数 一般情况下只用于删除带有空数据(NaN)的行。
insert()函数可以添加一列,但要指定参数如:df.insert(添加的位置,列名,值)
例:销售金额一列存在数据缺失(如第2行),可以通过insert()在后方插入新的一列来显示完整且正确的销售金额,并将销售单价和销售数量相乘的结果设为其值。
df.insert(8,"完整销售金额",df["销售单价"]*df["销售数量"])
append()函数可以在最后追加一行数据。ignore_index=True表示忽略新数据的索引号。
df.append({"收银员名称":"陈晨","单据号":101101111},ignore_index = True)
经过测试,Python3.7及以上版本set_value()函数已不可用。要根据行索引和列索引(也称列标题、字段名)修改某个值,可以使用“at”,方法如下:
修改第三行收银员名称为小明:
df.at[2,'收银员名称'] = '小明'
收银员名称 单据号 销售时间 ... 销售单价 销售数量 销售金额
0 陈晨 20000001 20141018072043 ... 1.7 1.0 1.7
1 陈晨 20000002 20141018073215 ... 4.4 1.0 NaN
2 小明 20000003 20141018073519 ... 86.9 1.0 86.9
3 陈晨 20000004 20141018073544 ... 7.2 1.0 NaN
4 陈晨 20000005 20141018073612 ... 5.6 1.0 5.6
... ... ... ... ... ... ...
65530 刘珍霞 20031877 20150228184246 ... 2.9 1.0 2.9
65531 刘珍霞 20031877 20150228184246 ... 4.5 1.0 4.5
65532 刘珍霞 20031877 20150228184246 ... 1.5 2.0 3.0
65533 刘珍霞 20031878 20150228184336 ... 10.9 1.0 10.9
65534 刘珍霞 20031878 20150228184336 ... 1.5 2.0 3.0
[65535 rows x 8 columns]
其中,df.at[2,'收银员名称']意为先选取该数据。之后再对其进行赋值。
值得注意的是at后面中
df.rename(columns = {"销售金额":"销售额"})
括号内前面的是行索引,后面的是列索引
拓展:rename()函数适合于修改个别的行列索引。
改列索引
df.rename(columns = {"销售金额":"销售额"})
改行索引
df.rename(index = {0:"起始"})
★★★对数据整理或计算时,经常需要对局部数据进行操作,此时选取数据的方法比较重要。
1. 根据列索引(列名、字段名)选取数据
选取一列:df[“列名”] 或 df.中文列名
选取多列:df[[“列名”,”列名”]]
2. 根据行索引选取数据
选取一行: df[n:n+1] n为索引号 注意!这里选取一行如果写df[n]会报错
选取连续多行:df[m:m+n] m,n为索引号
根据索引号来选取不连续的多行暂时不涉及,但有时可以根据条件筛选,如下所示:
①选取销售金额小于8.5的所有行:df[df['销售金额']<8.5]
②选取销售金额等于8.5的所有行:df[df['销售金额']==8.5]
3. 选择某行某列的数据
df.at[行索引,“列索引”]
使用count()函数统计数据集当中的非空行数
import pandas as pd
df = pd.read_csv(open("超市销售数据.csv"))
print(df.count())
结果如下
收银员名称 65535
单据号 65535
销售时间 65535
商品货号 65535
商品名称 65535
销售单价 65535
销售数量 65535
销售金额 65532
dtype: int64
使用sort_values()可以对数据排序,通过axis=0/1确定行/列排序(一般情况都会以行为单位调整顺序),通过ascending = 1/0 或 True/False确定升/降序。
以销售数量的多少按降序对行进行排序
df = df.sort_values("销售数量",axis=0,ascending=False)
结果如下:
收银员名称 单据号 销售时间 ... 销售单价 销售数量 销售金额
64707 刘珍霞 20031520 20150227142158 ... 1.40 300.0 420.0
17127 欧阳莉芳 20008359 20141119185659 ... 1.50 50.0 75.0
42122 刘珍霞 20020491 20150115090634 ... 6.30 48.0 302.4
59018 陈晨 20028923 20150216193252 ... 20.00 40.0 800.0
3197 王金萍 20001529 20141022150902 ... 3.40 33.0 112.2
... ... ... ... ... ... ...
7005 欧阳莉芳 20003448 20141029131106 ... 1.15 -4.0 -4.6
37500 陈晨 20018309 20150104145203 ... 1.50 -4.0 -6.0
18507 陈晨 20009055 20141122120328 ... 7.20 -10.0 -72.0
18506 陈晨 20009055 20141122120328 ... 7.40 -10.0 -74.0
60283 陈晨 20029517 20150219133542 ... 11.00 -20.0 -220.0
[65535 rows x 8 columns]
head( )、tail( ):返回前n个、后n个数据记录;如head(3),就返回前3行数据,括号内不写默认为5
max( )、min( ):返回最大值、最小值;
sum( )、mean( ):求和、求平均值,通过 axis = 1/0确定行/列 和drop函数中的axis用法相反!
groupby()可以对DataFrame对象各列或各行中的数据进行分组,然后对其中每一组数据进行不同的操作。
例子:按照销售员名称进行分类,然后统计非空行数
import pandas as pd
df = pd.read_csv(open("超市销售数据.csv"))
print(df.groupby('收银员名称').count())
结果如下
单据号 销售时间 商品货号 商品名称 销售单价 销售数量 销售金额
收银员名称
刘珍霞 10044 10044 10044 10044 10044 10044 10044
朱姣艳 297 297 297 297 297 297 297
欧阳莉芳 21297 21297 21297 21297 21297 21297 21297
王金萍 2376 2376 2376 2376 2376 2376 2376
陈晨 31521 31521 31521 31521 31521 31521 31518
注意!如果只写了print(df.groupby('列索引'))是看不到结果的,我们在写代码测试时一定要在groupby()之后加上某个函数
拓展:使用len()函数还可以求出分组的组数
temp = df.groupby('收银员名称').count()
print(len(temp))
输出结果为:5
在实际操作中分组之后往往会用matplotlib绘制统计图表,而绘制统计图时往往需要先获取图像x轴和y轴的数据,这两个数据一般使用列表的形式,那么如何从统计好的数据中得到这两个数据呢?
假设我们要绘制如下图表来展示不同收银员的销售金额
我们首先要获取他的x轴也就是每个收银员的名称,按照上面我们讲的访问列的方法写出以下代码
x = df.收银员名称
print(x)
这时候输出x的结果会报错AttributeError: 'DataFrame' object has no attribute '收银员名称'
这是因为在groupby()函数中自带一个as_index的参数,这个参数很容易被忽略,如果不写的话,他的值默认为True,他的意思是把第一列数据作为整个二维表的行索引,仔细观察你就会发现整个第一列被往下移动了一格
这就是为什么会报错说找不到“收银员名称”这个索引的原因。
由此可见当groupby后面没有填as_index这个参数或者填了as_index=True时,我们不能用这个方法访问到该列数据,而应该使用.index来获取全部的行索引
x = df.index
print(x)
成功获取到了!结果如下
Index([' 刘珍霞', ' 朱姣艳', ' 欧阳莉芳', ' 王金萍', ' 陈晨'], dtype='object', name='收银员名称')
同理可得.values可以用来获取每一行存放的值,之后会细讲
那么如果我们一定要用x = df.收银员名称或者x = df["收银员名称"]来获取到相应数据的话,我们应该把代码改为
print(df.groupby('收银员名称',as_index=False).count())
而y轴所需要的数据我们则可以直接用y = df.销售金额来获取到
分完组的数据中往往存在许多没用的数据,我们在处理过程中可能会先对分完组的数据处理,保留我们需要的数据,继续上面的例子
我们在分组后的数据后进一步筛选取得只保留销售数量的的数据
import pandas as pd
df = pd.read_csv(open("超市销售数据.csv"))
temp = df.groupby('收银员名称').count().销售数量
print(temp)
这时会输出如下的series数据
收银员名称
刘珍霞 10044
朱姣艳 297
欧阳莉芳 21297
王金萍 2376
陈晨 31521
Name: 销售数量, dtype: int64
很显然,因为没有设置参数as_index“收银员名称”这一列直接成为了行索引
如果设置as_index=False输出结果如下,他是会自动补充数字行索引的
0 10044
1 297
2 21297
3 2376
4 31521
Name: 销售数量, dtype: int64
同时会发现这个数据没有了列索引,这时候如果我们要获取图表y轴的数据,也就是每个员工的销售金额,我们应该使用.values来获取
print(temp.values)
我们就成功得到了如下数据
[10044 297 21297 2376 31521]
综上所述,在做类似这样先分组后绘图的题目一定要注意代码中的groupby()函数中的as_index的使用情况以及行列索引的情况从而选择合适的方法取得所需数据!