龙空技术网

数据可视化:认识Pandas

马拉松程序员 55

前言:

如今兄弟们对“pandas获取列表长度”大体比较看重,兄弟们都需要剖析一些“pandas获取列表长度”的相关文章。那么小编也在网络上汇集了一些对于“pandas获取列表长度””的相关资讯,希望同学们能喜欢,兄弟们快快来了解一下吧!

Pandas是一个强大的分析结构化数据的工具集,它的使用基础是Numpy,用于数据挖掘和数据分析,同时也具有数据清洗功能。

Pandas简介

Pandas也是Python数据分析和实战的必备工具包之一,它提供了快速灵活的数据结构,简单的直观的处理关系型数据。可以方便的处理像Excel或者数据库中这样的结构化的数据。Pandas是基于NumPy开发,并且是开源的分析工具。从0.25.x系列版本开始,Pandas仅支持Python 3.5.3及更高版本。未来的版本中将提高到3.6,在不管什么时候开始学习,可以选择使用最新版的Python和Pandas。

Panda的官网是 同样也是纯英文的网站,有能力的读者在学习使用Pandas时,可以查阅官网的第一手资料。

开始正式介绍Pandas之前,先来举一个简单的例子。假设一个数学老师需要统计班级上期末考试的分数情况,一般的都是会看下班上最高分,最低分,平均分,中位分数等等各种数据指标,那么Pandas就可以一步到位处理。

#导入pandas库import pandas as pd#假设数据为数据成绩,以6个例子data1 = [80, 88, 94, 85, 86, 90]a = pd.Series(data1)print(a.describe())#代码运行结果:count     6.000000mean     87.166667std       4.750439min      80.00000025%      85.25000050%      87.00000075%      89.500000max      94.000000dtype: float64

Pandas中describe()方法可以快速的描述一组数据的概况。基本内容是:count为元素个数,mean为平均数,std为标准差,min是最小值,max是最大值,25%、50%、75%表示的此分位数值。

当然在教学组长眼中,并不仅仅局限一个班的情况,可能是需要统计10个班甚至20个班的成绩情况,可以直接比较那个班级的分数情况高低。

#导入pandas库import numpy as npimport pandas as pd#每个数组代表一个班级成绩data2 = [[80, 88, 94, 85, 86, 90],[82, 81, 93, 92, 97, 78]]#生成narray对象a = np.array(data2)#pandas加载对象b = pd.DataFrame(a.T)print(b.describe())#代码运行结果:0          1count   6.000000   6.000000mean   87.166667  87.166667std     4.750439   7.782459min    80.000000  78.00000025%    85.250000  81.25000050%    87.000000  87.00000075%    89.500000  92.750000max    94.000000  97.000000

当然Pandas的功能并不止于此,接下来将我们了解Pandas的基础知识点。

Pandas数据结构

Series

在Pandas中,最常用的就是数据结构就是Series和DataFrame。Series是带标签的一维数组,可以储存的数字、字符串等常见对象。调用pd.Series()即可创建Series

#导入pandas库import pandas as pddata = [80, 88, 'a', 21.5]a = pd.Series(data)print(a)print(type(a))#代码输出结果:0      801      882       a3    21.5dtype: object<class 'pandas.core.series.Series'>

当打印Series对象a的时候左边会默认带着index,也就是索引,index也可以显式的指定,长度必须跟data长度一致,否则会报错:ValueError。当然即便是指定索引,也还是可以使用原来默认的索引查询数据。

import pandas as pddata = [80, 88, 'a', 21.5]a = pd.Series(data, index=['a', 'b', 'c', 'd'])print(a)print(a['b'])print(a[0])#代码输出结果:a      80b      88c       ad    21.5dtype: object8880

注意:在Pandas 中,索引值可以重复。

import pandas as pddata = [80, 88, 'a', 21.5]a = pd.Series(data, index=['a', 'b', 'b', 'd'])print(a['b'])#代码运行结果:b    88b     adtype: object

另外还可以使用字典对象创建Series,key会成为index值,Value会成为data值

import pandas as pddata = {'a': 90, 'b': 22.3, 'c': 'Python'}a = pd.Series(data)print(a)print(a['b'])print(a[0])#代码运行结果:a        90b      22.3c    Pythondtype: object22.390

如果字典对象中指定上index后,会根据指定的index值重排序。如果值缺少,Pandas会使用NaN(Not a Number)代替。

import pandas as pddata = {'a': 90, 'b': 22.3, 'c': 'Python'}a = pd.Series(data, index=['c', 'b', 'a', 'd'])print(a)#代码运行结果:c    Pythonb      22.3a        90d       NaNdtype: object

Series 操作与 ndarray 类似,支持大多数 NumPy 中的函数,并且也支持索引切片。

import pandas as pddata = {'a': 90, 'b': 22.3, 'c': 'Python'}a = pd.Series(data, index=['c', 'b', 'a', 'd'])print(a[0])print(a[:2])#索引切片,取去a[0]-a[2]#代码运行结果:Pythonc    Pythonb      22.3dtype: object

另外在Series的初始化中还有一些其他属性:

__init__(self, data=None, index=None, dtype=None, name=None, copy=False,fastpath=False)

除了data,index,上面见到过,dtype跟NumPy中的一样的,还有name属性,就是可以给当前的Series对象赋值一个名字。Copy是布尔值,如果为True,则拷贝输入数据。

import pandas as pddata = [1, 2, 3]a = pd.Series(data, name="num")print("a对象的名称是:" + a.name)#代码运行结果:a对象的名称是:num

DataFrame

DataFrame是由多种类型的列构成的二维标签数据结构,可以理解做为Excel表格或者数据库中的表。DataFrame 是最常用的 Pandas 对象,与 Series 一样,DataFrame 支持多种类型的输入数据。

import pandas as pd#使用Series 字典创建DataFramed = {'a': pd.Series([1, 2, 3]),'b': pd.Series([4, 5, 6]),'c': pd.Series([7, 8, 9])}df = pd.DataFrame(d)print(df)#代码运行结果:a  b  c0  1  4  71  2  5  82  3  6  9

DataFrame的结构可以比作excel表格的内容,当然也可以直接使用一个二维数组来生成DataFrame,比如:

import pandas as pdd = {'a': pd.Series([1, 2, 3]),'b': pd.Series([4, 5, 6]),'c': pd.Series([7, 8, 9])}df = pd.DataFrame(d)print(df)#代码运行结果:0  1  20  1  2  31  4  5  62  7  8  9

还可以是用列表字典来创建DataFrame

import pandas as pdd = [{'a': 1, 'b': 2}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'c': 9}]df = pd.DataFrame(d)print(df)#代码运行结果:a    b    c0  1  2.0  NaN1  4  5.0  6.02  7  NaN  9.0

由此可以看出,DataFrame也是 Series 的容器,Series 则是标量的容器。DataFrame处理表格数据的时候,虽然也是二维数据,但是使用index(行)或 columns(列)比 axis 0(0轴) 和 axis 1 (1轴)更直观。用这种方式迭代 DataFrame 的列,可以使代码更整洁易读。

import pandas as pdd = [{'a': 1, 'b': 2}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'c': 9}]df = pd.DataFrame(d)for col in df.columns:print(type(df[col]))print(df[col])#代码运行结果:<class 'pandas.core.series.Series'>0    11    42    7Name: a, dtype: int64…

两者的数据结构差别如表所示

名称

维度

描述

Series

1

带标签的一维同构数组

DataFrame

2

带标签的大小可变的二维异构表格

Pandas 所有数据结构的值都是可变的,数据结构的大小不都是可变的,Series 的长度不可改变,但是DataFrame里就可以插入新的列。

Pandas常用操作

查看数据

在更多的时候,做数据分析,往往会从外部读取数据,常用的读取从excel表格数据,DataFrame可以便捷的去读excel数据。我们在5.1.4中已经抓取到了豆瓣TOP250的电影信息,并且将信息保存为movie.xlsx。以下示例中均是采用movie.xlsx文件的内容,读者可以先按照5.1.4小节的方法将数据抓取到本地。

import pandas as pddf = pd.read_excel('movie.xlsx')print(df)代码运行结果:
import pandas as pddf = pd.read_excel('movie.xlsx')print(df.head())#查看 DataFrame 头部数据print(df.tail(2)) #查看 DataFrame 尾部数据代码运行结果:

使用head()和tail()方法可以查看头部和尾部的数,默认是5条,可以自定义设置条数。参数几为查看的条数。

import pandas as pddf = pd.read_excel('movie.xlsx')#DataFrame对象的基本信息print(df.info())#代码运行结果:<class 'pandas.core.frame.DataFrame'>RangeIndex: 249 entries, 0 to 248Data columns (total 8 columns):#   Column   Non-Null Count  Dtype---  ------   --------------  -----0   电影名称     249 non-null    object1   上映年份     249 non-null    int642   导演       249 non-null    object3   类型       249 non-null    object4   评价分数     249 non-null    float645   评价人数     249 non-null    int646   制片国家/地区  249 non-null    object7   语言       249 non-null    objectdtypes: float64(1), int64(2), object(5)memory usage: 15.7+ KBNone

在本小节开头的位置,提到了一个方法就是describe(),这是一个非常简洁的方法,可以快速的描述出数据的大体情况。因为dateframe默认会使用科学计数法,如果数据比较大,得出来数据不是很美观,所以可以设置pandas的参数,

import pandas as pddf = pd.read_excel('movie.xlsx')#为了格式化数据,不使用科学计数法,保留一位小数pd.set_option('display.float_format', lambda x: '%.1f' % x)print(df.describe())#代码运行结果:上映年份  评价分数      评价人数count  249.0  249.0     249.0mean  2000.5   8.9  586291.0std     15.8   0.3  369609.5min   1931.0   8.4  106212.025%   1995.0   8.7  341114.050%   2004.0   8.9  483692.075%   2011.0   9.1  702971.0

选择数据

选择单列,产生一个Series,使用[]切片选择行。

import pandas as pddf = pd.read_excel('movie.xlsx')#选择单列print(df['上映年份'])#选择前三行print(df[0:3])#代码运行结果:0      20101      19882      20093      20024      1998...244    1988245    2004246    2001247    2013248    1997Name: 上映年份, Length: 249, dtype: int64电影名称  上映年份         导演  类型  评价分数     评价人数 制片国家/地区   语言0      怦然心动 Flipped  2010      罗伯·莱纳  剧情   9.1  1457992      美国   英语1        龙猫 となりのトトロ  1988        宫崎骏  动画   9.2  1031042      日本   日语2  三傻大闹宝莱坞 3 Idiots  2009  拉吉库马尔·希拉尼  剧情   9.2  1538779      印度  印地语

除了使用[] 直接访问,还可以使用Pandas 优化过的数据访问方法,比如loc()和iloc()等,loc意思为location,是功能强大的选择方法。iloc中i的意思是指integer,所以它只接受整数作为参数。数值都是index的值,从0开始,即0表示第一行。

import pandas as pddf = pd.read_excel('movie.xlsx')# 选择第一行数据print(df.loc[0])print("--------------")#选择第1-4行数据,包括第4(index=3)行数据的‘电影名称’print(df.loc[0:3, '电影名称'])print("--------------")#选择第3-4行数据不包括第5(index=5)行,第1-3列数据不包括第4行(index=3)print(df.iloc[2:4, 0:3])#代码运行结果:电影名称       怦然心动 Flipped上映年份               2010导演                罗伯·莱纳类型                   剧情评价分数                9.1评价人数            1457992制片国家/地区              美国语言                   英语Name: 0, dtype: object--------------0        怦然心动 Flipped1          龙猫 となりのトトロ2    三傻大闹宝莱坞 3 Idiots3             无间道 無間道Name: 电影名称, dtype: object--------------电影名称  上映年份         导演2  三傻大闹宝莱坞 3 Idiots  2009  拉吉库马尔·希拉尼3           无间道 無間道  2002        刘伟强

除了loc()和iloc(),还可以使用at()和iat(),作用是获取某个位置的值。

import pandas as pddf = pd.read_excel('movie.xlsx')print(df)# 获取index是3 column是'电影名称'的值print(df.at[3, '电影名称'])# 获取index是2 ,第2列的内容print(df.iat[2, 1])#代码运行结果:无间道 無間道2009

在选择或者查询数据的时候,肯定会带又一些条件,这时候我们可以直接选择某一个列,进行条件筛选,得到想要的数据,比如说,我们想查一下最近10年上映的评分高于9分的电影。

import pandas as pddf = pd.read_excel('movie.xlsx')print(df[df.上映年份 > 2016][df.评价分数 > 9.0])print(len(df[df.评价分数 > 9.0]))#代码运行结果:电影名称  上映年份      导演   类型  评价分数     评价人数 制片国家/地区    语言36   何以为家 كفرناحوم  2018  娜丁·拉巴基   剧情   9.1   807449     黎巴嫩  阿拉伯语45      寻梦环游记 Coco  2017  李·昂克里奇   喜剧   9.1  1276741      美国    英语103    人生果实 人生フルーツ  2017    伏原健之  纪录片   9.5   131655      日本    日语

这样可以通过设置条件选择出来我们想要的数据,或者统计出来简单的数据结果,比如说分别统计一下从20世纪30年代到21世纪20年代,这100年中的高质量影片数量分布情况,看下哪个10年的电影文化产业发展的更好,还可以结合当时的历史背景等等得出一些结论。这就是做了一次简单的数据分析,感兴趣的读者可以尝试一下。

转置数据

import pandas as pddf = pd.read_excel('movie.xlsx')#直接使用.T获得转置数据print(df.T)#代码运行结果:0           1    ...                     247           248电影名称    怦然心动 Flipped  龙猫 となりのトトロ  ...  再次出发之纽约遇见你 Begin Again 千钧一发 Gattaca上映年份             2010        1988  ...                    2013          1997导演              罗伯·莱纳         宫崎骏  ...                   约翰·卡尼       安德鲁·尼科尔类型                 剧情          动画  ...                      喜剧            剧情评价分数              9.1         9.2  ...                     8.6           8.8评价人数          1457992     1031042  ...                  343860        209917制片国家/地区            美国          日本  ...                      美国            美国语言                 英语          日语  ...                      英语            英语[8 rows x 249 columns]

排序数据

Pandas中排序使用的是sort_values(),详细方法和主要使用的参数如下:

sort_values(by,axis=0,ascending=True,inplace=False,kind="quicksort",na_position="last",ignore_index=False)

by:依照排序的列

ascending:bool型,True为升序,False为倒叙。默认为升序

kind:排序方法,{‘quicksort’, ‘mergesort’, ‘heapsort’}, 默认是使用‘quicksort’。

import pandas as pd#为了方便查看,选择Excel表格中的指定列df = pd.read_excel('movie.xlsx', usecols=['电影名称', '上映年份', '制片国家/地区'])print(df.sort_values(by="上映年份"))#代码运行结果:电影名称  上映年份 制片国家/地区207           城市之光 City Lights  1931      美国82           摩登时代 Modern Times  1936      美国23     乱世佳人 Gone with the Wind  1939      美国190       魂断蓝桥 Waterloo Bridge  1940      美国194                    罗生门 羅生門  1950      日本..                         ...   ...     ...185                 小偷家族 万引き家族  2018      日本191  波西米亚狂想曲 Bohemian Rhapsody  2018      英国145      头号玩家 Ready Player One  2018      美国55              绿皮书 Green Book  2018      美国183                    寄生虫 기생충  2019      韩国[249 rows x 3 columns]

通过对TOP250高分电影的上映年代排序,可见排名前三的都是美国出品的,而且时间都是在19世纪40年代,可见美国的电影事业起步还是比较早,当时中国还是处于动乱时代,对于电影这种文化产业的发展根本没有基础。

如果设置ascending为False,则是倒叙排列,如果将by设置为“评价分数”,则是以分数排序,同样可以设置两个排序维度。下面演示一下,根据上映年份和评价分数两个维度来进行排序。

import pandas as pd#注意这里需要添加‘评价分数’,不然会报keyError错误df = pd.read_excel('movie.xlsx', usecols=['电影名称', '上映年份', '评价分数', '制片国家/地区'])print(df.sort_values(by=['上映年份', '评价分数']))#代码运行结果:电影名称  上映年份  评价分数 制片国家/地区207           城市之光 City Lights  1931   9.3      美国82           摩登时代 Modern Times  1936   9.3      美国23     乱世佳人 Gone with the Wind  1939   9.3      美国190       魂断蓝桥 Waterloo Bridge  1940   8.8      美国194                    罗生门 羅生門  1950   8.8      日本..                         ...   ...   ...     ...191  波西米亚狂想曲 Bohemian Rhapsody  2018   8.7      英国55              绿皮书 Green Book  2018   8.9      美国24                       我不是药神  2018   9.0    中国大陆36               何以为家 كفرناحوم  2018   9.1     黎巴嫩183                    寄生虫 기생충  2019   8.7      韩国[249 rows x 4 columns]

得到的结果是先按照上映年份升序排序,在按照评价分数升序排序。当然可以反过来,只不过需要在by参数列表中,更换下排序列的顺序。

6.2.4 Pandas缺失值处理

有时候我们拿到的原始数据的质量并不好,有很多缺失值,这是很正常的情况。通常,有两个处理方法,第一个是去掉缺失值,如果某一条数据中是NaN,那么就去掉这一条,使用dropna()方法。另外一个就是将缺失值按照默认值填充,使用filln()方法。这两种方法都可以按照具体的情况来处理。

import pandas as pd# 构建原始数据data = {'a': [1, 2, 3],'b': [4, None, 7],'c': [7, 8, None]}df = pd.DataFrame(data)print("原始数据:")print(df)print("删除缺失值:")print(df.dropna())print("填充缺失值:值为1")print(df.fillna(value=1))#代码运行结果:原始数据:a    b    c0  1  4.0  7.01  2  NaN  8.02  3  7.0  NaN删除缺失值:a    b    c0  1  4.0  7.0填充缺失值:值为1a    b    c0  1  4.0  7.01  2  1.0  8.02  3  7.0  1.0
Pandas数据统计和整合

数据统计

在Series中有一个很常用的方法就是value_counts(),它的作用就是统计Series中每个元素出现的次数。比如,在movie.xlsx中已经是250 部高分电影的数据,我们想知道这些电影都是哪些国家制作的,哪些年份上映的,我们就可以通过value_counts()方法来统计。

import pandas as pddf = pd.read_excel('movie.xlsx')#统计每年上映的电影数的前十年份print(df['上映年份'].value_counts()[:10])#统计制作国家的电影数的前十国家/地区print(df['制片国家/地区'].value_counts()[:10])#代码运行结果:2010    132004    131994    122013    112003    102008    102001     92006     92009     92014     9Name: 上映年份, dtype: int64美国      111日本       34中国香港     20英国       17中国大陆     15韩国       11法国        7意大利       6中国台湾      6德国        5Name: 制片国家/地区, dtype: int64

通过对年份统计结果,可以粗略的看出来2010年、2004年和1994年上映电影的质量都很高。而通过对制作国家的统计,看出来TOP250部高分电影中,有111部是美国制作。数量远高于第二名日本的34部。可见在电影文化产业,美国发展起步早,制作水平是世界领先水平。

这是通过value_counts()方法可以统计出来的原始数据,如果作为数据分析的结果呈现出来,稍微有点生涩,后面我们可以使用matlab来绘制更直观的图表。

数据整合

前面说过可以把dateframe看出是SQL表数据,那么在SQL中常用的连接、聚合等操作在Pandas中也是可以实现的。

import pandas as pddata1 = {'a': [1, 2], 'b': [3, 4]}data2 = {'a': [1, 3], 'b': [7, 8]}#dateframe对象A比作表AA = pd.DataFrame(data1)#dateframe对象B比作表BB = pd.DataFrame(data2)print(A)print(B)#代码运行结果:a  b0  1  31  2  4a  b0  1  71  3  8

可以简单的看为,A表中字段名为a和b,有两行数据。B表中同样字段名为a和b也有两行数据,接下来我们做一个连接操作,就是SQL语句中的join操作。

import pandas as pddata1 = {'a': [1, 2], 'b': [3, 4]}data2 = {'a': [1, 3], 'b': [7, 8]}a = pd.DataFrame(data1)b = pd.DataFrame(data2)# 以a列为准,默认是内连接 (inner join)print("内连接")print(pd.merge(a, b, on="a"))# 以a列为准,连接方式为左连接(left join)print("左连接")print(pd.merge(a, b, on="a", how="left"))# 以a列为准,连接方式为右连接(right join)print("右连接")print(pd.merge(a, b, on="a", how="right"))# 以a列为准,连接方式为外连接(outer join)print("外连接")print(pd.merge(a, b, on="a", how="outer"))#代码运行结果:内连接a  b_x  b_y0  1    3    7左连接a  b_x  b_y0  1    3  7.01  2    4  NaN右连接a  b_x  b_y0  1  3.0    71  3  NaN    8外连接a  b_x  b_y0  1  3.0  7.01  2  4.0  NaN2  3  NaN  8.0

结果跟SQL中的连接操作是一致的。内连接得到两个对象中都有的数据,对象A中a列和对象B中的a列都有1。左连接以对象A的a列为准,对象B中a列中没有的值,则取空。右连接则以对象B的a列为准。外连接则查询出全部的数据。

同样除了连接操作还有聚合操作,与SQL中的使用groupby对列进行聚合操作一样。

import pandas as pddata1 = {'a': [1, 2], 'b': [3, 4]}data2 = {'a': [1, 3], 'b': [7, 8]}a = pd.DataFrame(data1)b = pd.DataFrame(data2)# 连接两个对象做为一个对象print(pd.concat([a, b]))# 按照a列统计计数print(pd.concat([a, b]).groupby('a').count())# 按照a列求和print(pd.concat([a, b]).groupby('a').sum())#代码运行结果:a+ba  b0  1  31  2  40  1  71  3  8计数ba1  22  13  1求和ba1  102   43   8

熟悉SQL查询的读者对这个操作并不会很陌生,操作等价于下面使用SQL语句查询的结果。可以直观的看出,count()按照a列的值计数,值为1的有2个,值为2,3的有1个。Sum()操作在实际应用场景中通过会用于按照月份或者年度统计销售额等等。

--按照a列统计计数Select a, count(a) from A group by a ;--按照a列统计计数Select a, sum(b) from A group by a ;

标签: #pandas获取列表长度