Python数据分析之pandas

Python数据分析之Pandas

Python Data Analysis Librarypandas是基于NumPy的一种工具,该工具是为了解决数据分析任务而创建的
Pandas纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

import pandas as pd
import numpy as np

Pandas中有两种常用的基本结构

  • Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近。Series能保存不同种数据类型,字符串、boolean值、数字等都能保存在Series中。
  • DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。

Series类型

一维Series可以用一维列表初始化:

s = pd.Series([1,2,3,np.nan])
'''
0    1.0
1    2.0
2    3.0
3    NaN
dtype: float64
'''
s = pd.Series([1,2,3,np.nan],index=['a','b','c','d'])
'''
a    1.0
b    2.0
c    3.0
d    NaN
dtype: float64
'''

默认情况下,Series的下标都是数字(可用使用额外参数指定),类型都是统一的。

索引-数据的行标签

print(s.index) # Index(['a', 'b', 'c', 'd'], dtype='object')

获取值

print(s.values) # [ 1.  2.  3. nan]
print(s['a']) # 1.0

切片操作(不会改变原数组)

print(s[2:5])
print(s[::2])

索引赋值

s.index.name = "索引"
'''
索引
a    1.0
b    2.0
c    3.0
d    NaN
dtype: float64
'''
s.index = list('abcd')
s['a':'d']

DataFrame类型

DataFrame是一个二维结构,这里首先构造一组时间序列,作为我们第一维的小标

date = pd.date_range('20180101',periods=6)
'''
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
               '2018-01-05', '2018-01-06'],
              dtype='datetime64[ns]', freq='D')
'''

创建DataFrame结构

df = pd.DataFrame(np.random.randn(6,4)) # 生成六行四列是随机数
'''
          0         1         2         3
0  1.349121  0.429305  1.481158  1.842555
1 -2.082420 -0.993061  0.651757 -0.350710
2  1.137187  1.685110  0.379327 -1.079704
3  0.578643  0.384072  1.297785 -0.465521
4  0.390983 -0.656692  0.762707 -0.281309
5 -0.365502  0.376358 -2.595183  0.634950
'''
df = pd.DataFrame(np.random.randn(6,4),index=date,columns=list('abcd'))
'''
                   a         b         c         d
2018-01-01  1.751509  0.791480 -0.848589 -1.286318
2018-01-02  0.268522  0.197771  0.241838 -0.649512
2018-01-03  0.897170 -0.639284  0.600405 -0.387560
2018-01-04 -0.161846 -0.592441  0.697815  0.424387
2018-01-05  0.800356 -0.517562  0.145399  0.634336
2018-01-06 -0.281471  0.164059  0.764360 -0.768802
'''

除了向DataFrame中传入二维数组外,我们也可以使用字典传入数据

df2 = pd.DataFrame({'A':1,'B':pd.Timestamp('20180101'),'C':pd.Series(1,index=list(range(4)),dtype=float),'D':np.array([3]*4,dtype=int)})
'''
   A          B    C  D
0  1 2018-01-01  1.0  3
1  1 2018-01-01  1.0  3
2  1 2018-01-01  1.0  3
3  1 2018-01-01  1.0  3
'''
df2.dtypes
'''
A             int64
B    datetime64[ns]
C           float64
D             int32
dtype: object
'''

字典的每个key代表一列,其value可以是各种能够转化为Series的对象。
与Series要求所有的类型都一致不同,DataFrame只要求每一列数据的格式相同

查看数据

头尾数据
head和tail方法可以分别查看最前面几行和最后面几行的数据(默认为5) :

df.head()
df.head(1)
df.tail()

下标使用index属性查看,列表使用columns属性查看,数据值使用values查看

df.index
df.columns
df.values

pandas读取数据及数据操作

读取excel表格

df = pd.read_excel('paiming.xlsx')
print(df.head(6))

行操作

# 获取某行
print(df.iloc[50:53])
# 添加某行
dit = {'名字':'hhh'}
s = pd.Series(dit)
s.name = 41452
df = df.append(s)
# 删除某行
df= df.drop([name])

列操作

df.columns
df['名字'][1:10]
df['名字','类型']
# 增加列
df['序号'] = range(1,len(df)+1)
# 删除列
df = df.drop['序号',axis=1] # axis=1表示列
# 通过标签选择数据
# df.loc[[index],[colunm]]
df.loc[[1,2],['名字','类型']]

条件选择

df[df['绩点'] == '3.1490']

df[((df['绩点'] == '3.1490')|(df['绩点'] == '3.3331')))&(df['学号']>3120002520)]

缺失值及异常值处理

缺失值处理方法:

方法说明
dropna根据标签中的缺失值进行过滤,删除缺失值
fillna对缺失值进行填充
isnull返回一个布尔值对象,判断哪些值是缺失值
notnullisnull的否定式
#判断缺失值
df[df['名字'].isnull()]

#填充缺失值
df['绩点'].fillna(0,inplace=True) # inplace表示替换原始数据

#删除缺失值
df.dropna()
'''
参数:
- how = 'all' 删除全部为空值的行或列
- inpalce = True 是否覆盖原数据
- axis = 0 选择行或者列
'''

异常值,即在数据集中存在不合理的值,又称离群点。比如年龄为-1,笔记本电脑重量为1吨等,都属于异常值的范围。
对于异常值,一般来说数量都会很少,在不影响整体数据分布的情况下,我们直接删除就可以了。
其他属性的异常值处理,我们会在格式转换部分,进一步讨论。

数据保存

数据处理后,将数据重新保存到movie_data.xlsx

df.to_excel('movie_data.xlsx')

数据格式转换

在做数据分析的时候,原始数据往往会因为各种各样的原因产生各种数据格式的问题。
数据格式是我们非常需要注意的一点,数据格式错误往往会造成很严重的后果。
并且,很多异常值也是我们经过格式转换之后才会发现,对我们规整数据,清洗数据有着重要的作用。

格式

查看格式

df['绩点'].dtype

转换格式

df['绩点']=df['绩点'].astype('int')

排序

默认排序

df[:10]

按某个列排序

df.sort_values(by='列名称',ascending=Flase)[:5] # ascending为True的话为顺序排序,False为逆序排序

多个值排序

df.sort_values(by=['第一优先列','第二优先列'])

基本统计分析

描述性统计

dataframe.describe()
'''
               排名            学号        高考成绩  ...    2021春季绩点    2021秋季绩点       总计平均分
count  603.000000  6.030000e+02  603.000000  ...  603.000000  603.000000  603.000000
mean   302.000000  3.132757e+09  575.701493  ...    2.694306    2.825201    3.134008
std    174.215384  3.339873e+07   54.071816  ...    0.775117    0.911435    0.605716
min      1.000000  3.118002e+09    0.000000  ...    0.000000    0.000000    0.000000
25%    151.500000  3.120002e+09  578.000000  ...    2.199950    2.310200    2.835641
50%    302.000000  3.120002e+09  579.000000  ...    2.786200    2.966600    3.212758
75%    452.500000  3.120003e+09  581.000000  ...    3.256800    3.489700    3.535538
max    603.000000  3.220003e+09  645.000000  ...    4.443100    4.661500    4.274842
'''
df[df['高考成绩']>580]

# 删除异常值
df.drop(df[df['高考成绩']>580].index,inplace=True)
df.index=range(len(df))# 将下标修改

通过描述性统计,可以发现一些异常值,很多异常值往往是需要我们逐步去发现的。

最值

df['高考成绩'].max()

最小值

df['投票人数'].min()

均值和中值

df['投票人数'].mean()
df['投票人数'].median()

方差和标准差

df['高考成绩'].var()
df['高考成绩'].std()

求和

df['高考成绩'].sum()

相关系数、协方差

df(['平均绩点','高考成绩']).corr()
df(['平均绩点','高考成绩']).cov()

计数(获取唯一值)

len(df)
df['产地'].unique()

我们通常的表格内容中包含了一些重复的数据,比如美国和USA,德国和西德,俄罗斯和苏联。这些数据名称上不同但需要通过数据替换的方法将这些相同合并替换掉

df['产地'].replace('USA','美国',inplace=True)
df['产地'].replace(['西德','苏联'],['德国','俄罗斯'],inplace=True)

计算某列中相同名称的数量的总和

df['产地'].value_counts()

保存数据

df.to_excel()

数据透视

Excel中数据透视表的使用非常广泛,其实Pandas也提供了一个类似的功能,名为pivot_table。
pivot_table非常有用,我们将重点解释pandas中的函数pivot_table。

使用pandas中pivot_table的一个挑战是,你需要确保你理解你的数据,并清楚地知道你想通过透视表解决什么问题。虽然pivot_table看起来只是一个简单的函数,但是它能够快速地对数据进行强大的分析。

基础使用

创建pivot_table

pd.set_option('display.max_columns', 10)
pd.set_option('display.max_rows', 10) # 定义行和列

pd.pivot_table(df,index = ['名字'])
'''
        总计平均分   排名  高考分数绩点折算  高考成绩  
姓名                                  
丁xx  2.474833  538  3.873333   581  
万xx  2.956733  415  3.853333   578  
于x   3.195592  314  4.086667   571  
于x   3.373225  228  4.080000   570  
付xx  2.105142  584  4.026667   586  
伍xx  3.467825  183  3.880000   582  
但xx  3.881017   39  4.046667   610  
何xx  1.787017  594  3.866667   580  
何xx  3.166258  326  3.873333   581  
何xx  3.025292  389  3.866667   580  

[10 rows x 12 columns]

Process finished with exit code 0

'''

也可以有多个索引。实际上,大多数的pivot_table参数可以通过列表获取多个值。

pd.pivot_table(df,index=['年代','产地'])

也可以指定需要统计汇总的数据。

pd.pivot_table(df,index=['年代','产地'],values=['评分'])

还可以指定函数,来统计不同的统计值

pd.pivot_table(df,index=["年代","产地"],values=["投票人数","评分"], aggfunc=[np.sum,np.mean])

加入margins=True,可以在下方显示一些总和数据。

pd.pivot_table(df, index=['产地'], aggfunc=[np.sum,np.mean],fill_value=0, margins=True)

对不同值执行不同的函数:可以向aggfunc传递一个字典。不过,这样做有一个副作用,那就是必须将标签做的更加简洁才行。

pd.pivot_table (df, index=['产地'],values=['投票人数''评分'],aggfunc={'投票人数':np. sum,'评分':np.mean}, fill_value=0)

透视表过滤

table-pd.pivot_table(df, index=['年代' ],values=['投票人数' , '评分' ], aggfunc={'投票人数' :np. sum,'评分':np.mean}, fill_value=0)

数据重塑和轴向逆转

层次化索引是pandas的一项主要功能,它能使我们在一个轴上拥有多个索引.

Series的层次化

Series的层次化索引:

s=pd.Series(np.arange(1,10), index=[['a','a','a','b','b','e','e','d','d'],[1,2,3,1,2,3,1,2,3]])
'''
a  1    1
   2    2
   3    3
b  1    4
   2    5
e  3    6
   1    7
d  2    8
   3    9
dtype: int32
'''
s.index
'''
MultiIndex([('a', 1),
            ('a', 2),
            ('a', 3),
            ('b', 1),
            ('b', 2),
            ('e', 3),
            ('e', 1),
            ('d', 2),
            ('d', 3)],
           )
'''

可以通过unstack方法可以将Series变成一个DataFrame

s.unstack()

也可以用stack将其转换回Series

s.unstack().stack()

Dataframe的层次化

Dataframe的层次化索引:

data=pd.DataFrame(np.arange(12).reshape(4,3),index=[['a','a','b','b'],[1,2,1,2]],columns=[[' A','A','B'],['Z','X','C'])

#设置列名称和行名称
data.columns.names = ['col1','col2']
data.rows.names = ['row1','row2']

#交换行索引
data.swaplevel('row1','row2')

将列变成索引 和 把索引变成列

df = df.set_index(['产地','年代'])
# 他的每一个索引都是一个元组

# 获取所有的美国电影,由于产地信息已经变成了索引,因此要是用.loc方法。
df.loc['中国']

# 取消层次化索引,把索引变回列
df = df.reset_index()

让数据的行列进行交换

data.T

dataframe也可以使用stack和unstack,转化为层次化索引的Series

data = data.stack()
data = data.unstack()

数据分组,分组运算

GroupBy技术:实现数据的分组y和分组运算,作用类似于数据透视表

按照电影的产地进行分组:

group = df.groupby(df['产地'])

可以计算分组后的各个统计量

group.mean()

计算每年的平均评分

df['评分'].groupby(df['年代'])

注意groupby只会对数值变量进行分组运算,所以有值不想参与运算时,可将其转化为字符串

df['年代'] = df['年代'].astype('str')
df.groupby(df['产地']).mean() # 我们会发现年代没有参与运算了

print(df.groupby([df['产地'],df['年代']]).mean())

离散化处理

在实际的数据分析项目中,对有的数据属性,我们往往并不关注数据的绝对取值,只关注它所处的区间或者等级。
比如,我们可以把评分9分及以上的电影定义为A,7到9分定义为B,5到7分定义为c,3到5分定义为D,小于3分定义为E。

离散化也可以称为分组、区间化

# Pandas为我们提供了方便的函数cut():
pd.cut(x,bins,right=True,labels=None,retbins=False,precision=3 ,include_lowest=False)

参数解释:

  • ×:需要离散化的数组、Series、DataFrame对象
  • bins:分组的依据
  • labels:每个分组的说明
    例子:
bins = np.percentile(df['投票人数'],[0,20,40,60,80,100])
df['热门程度']=pd.cut(df['投票人数'].bins,labels=['E','D','C','B','A'])

print(df[(df.热门程度=='A')&(df.评分等级=='E')])

合并数据集

  • append:先把数据集拆分为多个,再进行合并
df_usa=df[df.产地=='美国']
df_china=df[df.产地=='中国大陆']
  • merge:
pd.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=True,suffixes=('_x', '_y'),copy=True,indicator=False)
  • left: 拼接的左侧DataFrame对象
  • right: 拼接的右侧DataFrame对象
  • on: 要加入的列或索引级别名称。 必须在左侧和右侧DataFrame对象中找到。 如果未传递且left_index和right_index为False,则DataFrame中的列的交集将被推断为连接键。
  • left_on:左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
  • right_on: 左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
  • left_index: 如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键。 对于具有MultiIndex(分层)的DataFrame,级别数必须与右侧DataFrame中的连接键数相匹配。
  • right_index: 与left_index功能相似。
  • how: One of ‘left’, ‘right’, ‘outer’, ‘inner’. 默认inner。inner是取交集,outer取并集。比如left:[‘A’,‘B’,‘C’];right[’'A,‘C’,‘D’];inner取交集的话,left中出现的A会和right中出现的买一个A进行匹配拼接,如果没有是B,在right中没有匹配到,则会丢失。'outer’取并集,出现的A会进行一一匹配,没有同时出现的会将缺失的部分添加缺失值。
  • sort: 按字典顺序通过连接键对结果DataFrame进行排序。 默认为True,设置为False将在很多情况下显着提高性能。
  • suffixes: 用于重叠列的字符串后缀元组。 默认为(‘x’,’ y’)。
  • copy: 始终从传递的DataFrame对象复制数据(默认为True),即使不需要重建索引也是如此。
  • indicator:将一列添加到名为_merge的输出DataFrame,其中包含有关每行源的信息。 _merge是分类类型,并且对于其合并键仅出现在“左”DataFrame中的观察值,取得值为left_only,对于其合并键仅出现在“右”DataFrame中的观察值为right_only,并且如果在两者中都找到观察点的合并键,则为left_only。

基础实例:

import pandas as pd

left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                       'A': ['A0', 'A1', 'A2', 'A3'],
                       'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
result = pd.merge(left, right, on='key')

# on参数传递的key作为连接键
result
Out[4]: 
    A   B key   C   D
0  A0  B0  K0  C0  D0
1  A1  B1  K1  C1  D1
2  A2  B2  K2  C2  D2
3  A3  B3  K3  C3  D3

传入的on的参数是列表:

left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
                      'key2': ['K0', 'K1', 'K0', 'K1'],
                         'A': ['A0', 'A1', 'A2', 'A3'],
                         'B': ['B0', 'B1', 'B2', 'B3']})

right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                      'key2': ['K0', 'K0', 'K0', 'K0'],
                         'C': ['C0', 'C1', 'C2', 'C3'],
                         'D': ['D0', 'D1', 'D2', 'D3']})

result = pd.merge(left, right, on=['key1', 'key2'])
# 同时传入两个Key,此时会进行以['key1','key2']列表的形式进行对应,left的keys列表是:[['K0', 'K0'],['K0', 'K1'],['K1', 'K0'],['K2', 'K1']],
left的keys列表是:[['K0', 'K0'],['K1', 'K0'],['K1', 'K0'],['K2', 'K0']],因此会有1['K0', 'K0']2['K1', 'K0']对应。

result
Out[6]: 
    A   B key1 key2   C   D
0  A0  B0   K0   K0  C0  D0
1  A2  B2   K1   K0  C1  D1
2  A2  B2   K1   K0  C2  D2
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PrototypeONE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值