Python数据分析之Pandas入门(上)

前言

本系列共有三篇文章,依次按照pandas数据类型及其结构、内置模块对数据处理功能、可视化工具以及形如房价预测的案例分析内容展开介绍。本篇文章的代码均已测试通过,参考自书籍《Python for Data Analysis(Second Edition)》

Pandas 起初是作为金融数据分析工具被Wes McKinney开发出来的,其名称来源于面板数据(Panel Data)和Python 数据分析(Data Analysis),Panel Data 是经济学中关于多维数据集的一个术语;Pandas支持绝大部分NumPy风格的数组计算,不同的是,NumPy用于处理同质性的数值类型数组数据,而pandas是用来处理表格型或异质型数据的


一、 数据结构


1.Series()

pandas.Series(data, index, dtype, name, copy)

将数据展开成带索引值的一列

参数说明:

  • data:一组数据(ndarray 类型)

  • index:数据索引标签,如果不指定,默认从 0 开始。

  • dtype:数据类型,默认会自己判断

  • name:设置Series类的某个实例名称

  • copy:拷贝数据,默认为 False

import pandas as pd

a = ['Alex', 'Bob', 'Clara']
my_var = pd.Series(a, index=[1, 2, 3])

sites = {1: "Google", 2: "Runoob", 3: "Wiki"}
myvar = pd.Series(sites, index = [1, 2], name="RUNOOB-Series-TEST" )    # 若只需要字典的部分值,则在索引值中指定范围

print(my_var, '\n')
print(myvar)

输出为:

1     Alex
2      Bob
3    Clara
dtype: object 

1    Google
2    Runoob
Name: RUNOOB-Series-TEST, dtype: object

可以看到,pandas可接收列表和字典类型的数据作为Series类的创建对象,并能够按照序列进行索引,这样的切片操作可用于截取前num_request人数的信息。


# 可以认为Series是一个长度固定且有序的字典
import pandas as pd

sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
obj = pd.Series(sdata)
print(obj)

# 将字典的值按理想的键值排序
states = ['California', 'Oregon', 'Texas', 'Ohio', 'Utah']
obj = pd.Series(sdata, index=states)
print('\n重新排序后的字典:\n', obj)
print('\n检查缺失的数据:\n', pd.isnull(obj))       # 还可以用'pd.notnull(obj)',isnull和notnull也是Series中的实例方法: obj.isnull

输出为:

Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64

重新排序后的字典:
 California        NaN
Oregon        16000.0
Texas         71000.0
Ohio          35000.0
Utah           5000.0
dtype: float64

检查缺失的数据:
 California     True
Oregon        False
Texas         False
Ohio          False
Utah          False
dtype: bool

2.DataFrame()

pandas.DataFrame( data, index, columns, dtype, copy)

DataFrame 是一个矩阵的数据表,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引),可用分层索引展现更高维度的数据。

参数说明:

  • data:一组数据(ndarray、series, map, lists, dict 等类型)

  • index:索引值,或者可以称为行标签

  • columns:列标签,默认为 RangeIndex (0, 1, 2, …, n)

  • dtype:数据类型

  • copy:拷贝数据,默认为 False

从DataFrame中选区的列是数据的视图,而不是拷贝。对Series的修改会映射到DataFrame中去


①基本构造及属性

类型注释
2D ndarray数据的矩阵,行和列的标签是可选的参数
数组、列表和元组构成的字典每个序列成为DataFrame的一列,所有的序列必须长度相等
NumPy结构化/记录化数组与数组构成的字典一致
Series构成的字典每个值成为一列,每个Series的索引联合起来形成结果的行索引,也可以显式地传递索引
字典构成的字典每一个内部字典成为一列,键联合起来形成结果的行索引
字典或Series构成的列表列表中的一个元素形成DataFrame的一行,字典键或Series索引联合起来形成DataFrame的列标签
列表或元组构成的列表与2D ndarray的情况一致
其他DataFrame如果不显示传递索引,则会使用原DataFrame的索引
NumPy MaskeArray与2D ndarray的情况类似,但隐藏值会在结果DataFrame中成为NA/缺失值
  • 利用二维数组创建DataFrame
import pandas as pd

data = [['Google',1],['Baidu',2],['Wiki',3]]
df = pd.DataFrame(data,columns=['Site','Age'] ) # 给每一列添上标签

print(df)

(自动生成索引)输出为:

     Site  Age
0  Google    1
1   Baidu    2
2    Wiki    3

  • 利用多个同等长度的列表或NumPy数组组成的字典形成 DataFrame
import pandas as pd

data = {'name': ['Alex', 'Bob', 'Charlie', 'Dave', 'Emily'],
        'birth': [2001, 2000, 1989, 2001, 2003],
        'score': [96., 97.8, 99, 94., 90.3]}
frame = pd.DataFrame(data)
print(frame)
print('\n重新排序过的表格:\n', pd.DataFrame(data, columns=['name', 'score', 'birth']))
frame2 = pd.DataFrame(data, columns=['name', 'score', 'birth', 'gender'], index=['one', 'two', 'three', 'four', 'five'])
print('\n未初始化键值的指定列下会出现缺失值:\n',frame2)

# 可以按字典型标记或属性那样检索为:Series
print('\n检索姓名:\n', frame2['name'])
print('\n检索分数:\n', frame2.score)
# 通过位置或特殊属性进行选取
print('\n位置\'three\'索引:\n', frame2.loc['three'])

# 如果将Series赋值给一列时,Series的索引将会按照DataFrame的索引重新排列,并在空缺的地方填充缺失值
val = pd.Series(['F', 'M', 'M'], index=['five', 'one', 'two'])
frame2['gender'] = val
print('\n补充上空缺值后:\n', frame2)

del frame2['birth']
print('\n删除生日一列后:\n', frame2)

②索引对象

方法描述
append将额外的索引对象粘贴到原数据结构中后,产生一个新的索引
diffarance计算两索引的差集
intersection计算两索引的交集
union计算两索引的并集
isin计算表示每一个值是否在传值容器中的布尔数组
delete将位置i的元素删除,并产生新的索引
drop根据传参删除指定索引值,并产生新的索引
insert在位置i插入元素,并产生新的索引
is_monotonic如果索引序列递增的话返回True
is_unique如果索引序列惟一的话返回True
unique计算索引的唯一值序列
import pandas as pd
import numpy as np

obj = pd.Series(range(3), index=['a', 'b', 'c'])
index = obj.index
print(index[1:])

# 索引对象不可变,因此用户不可修改;但根据索引对象可以修改对应的值
# 不变性使得在多种数据结构中分享索引对象更安全
labels = pd.Index(np.arange(3))
obj1 = pd.Series([1.5, -1, 0], index=labels)
print("labels is obj1.index: ", labels is obj1.index)

# 与Python集合不同,pandas索引可以包含重复标签
dup_labels = pd.Index(['Apple', 'Banana', 'Apple', 'Pear'])
print(dup_labels)

3.Panel()

pandas.Panel(data=None, items=None, major_axis=None, minor_axis=None, copy=False, dtype=None)

pandas.Panel() represents wide format panel data, stored as 3-dimensional array

参数说明:

  • data : ndarray (items x major x minor), or dict of DataFrames

  • tems : Index or array-like
    axis=0
    major_axis : Index or array-like
    axis=1
    minor_axis : Index or array-like
    axis=2

  • dtype : dtype, default None

  • Data type to force, otherwise infer

  • copy : boolean, default False

  • Copy data from inputs. Only affects DataFrame / 2d ndarray input


二、基本功能


1.重建索引

obj.reindex(index, method, fill_value, limit, tolerance, level, copy)

用于创建一个个符合新索引的新对象。

参数说明如下:

  • index: 新建作为索引的序列,可以是索引实例或任意其他序列型Python数据结构,索引使用时无需复制

  • method: 插值方式,'ffill’为前向填充,'bfill’是后向填充

  • limit: 当前向或后向填充时,所需填充的最大尺寸间隙(以元素数量)

  • tolerance: 当前向或后向填充时,所需填充的不精确匹配下的最大尺寸间隙(以绝对数字距离)

  • level: 匹配MultiIndex级别的简单索引;否则选择子集

  • copy: 如果为True,即使新索引等于旧索引,也总是复制底层数据;如果是False,则在索引相同时不要复制数据

import pandas as pd

obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
print("obj2按照新的顺序排列后:\n", obj2)           # 即改变行索引

obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
print("\nobj3数据对象如下所示:\n", obj3)
print("\nobj3数据对象插值后如下所示:\n", obj3.reindex(range(6), method='ffill'))

# 既可以改变行索引,也可以改变列索引
obj3 = pd.DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['number', 'color', 'level'])
print("\nobj3数据对象重置后如下所示:\n", obj3)
frame = obj3.reindex(columns=['number', 'Like', 'color'])
print("\nobj3数据对象改变列索引后如下所示:\n", frame)
print("\nobj3数据对象改变行索引后如下所示:\n", obj3.reindex(['a', 'b', 'c', 'd']))


2.轴向上删除条目

drop()方法会返回一个含有指示值或轴向上删除值的新对象

import pandas as pd

data = pd.DataFrame(np.arange(16).reshape((4, 4)), 
                    index=['Ohio', 'Colorado', 'Utah', 'New York'], 
                    columns=['one', 'two', 'three', 'four'])
print(data)

# 在调用drop时使用“标签序列”会根据行标签删除值(轴0)
print("\n调用drop方法删除之后:\n", data.drop(['Colorado', 'Ohio']))
print("\n沿轴1,即\'axis=1\'或\'axis=columns\':\n", data.drop('two', axis=1))

# 该方法都是直接在源对象上操作,而不返回新对象;📢注意:inplace会清除被删除的数据
data.drop(['New York'], inplace=True)

3.索引、选择与过滤

  • 索引(详见1.2“索引对象”)
    • 普通索引(键值索引)
    • 切片索引
    • 条件索引
  • 选择(行标签索引)
    • .loc[]
    • .iloc()
  • 过滤(索引+切片)
类型描述
df[val]从DataFrame中选择单列或列序列;特殊情况的便利:布尔数组(过滤行),切片(切片行)或布尔值DataFrame
df.loc[val]根据标签选择DataFrame的单行或多行
df.loc[:, val]根据标签选择单列或多列
df.loc[val1, val2]同时选择行和列的一部分
df.iloc[where]根据整数位置选择单行或多行
df.iloc[:, where]根据整数位置选择单列或多列
df.iloc[where_i, where_j]根据整数位置选择行和列
df.at[label_i, label_j]根据行、列标签选择单个标量值
df.iat[i, j]根据行、列整数位置选择单个标量值
reindex方法通过标签选择行或列
get_value, set_value根据行和列的标签设置单个值
import pandas as pd
import numpy as np

""" 索引 """
obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
data = pd.DataFrame(np.arange(16).reshape((4, 4)), 
                    index=['Ohio', 'Colorado', 'Utah', 'New York'], 
                    columns=['one', 'two', 'three', 'four'])

# 普通的Python切片是不包含尾部的,但Series不一样
print(obj['b':'c'], '\n')
# 键值索引
print(data[['three', 'one']], '\n')
# 条件索引
print(data[data['three']>5], '\n')

""" 选择 """
print(data.loc['Colorado', ['two', 'three']], '\n')
print(data.iloc[2, [3, 0, 1]], '\n')      # 以NumPy的语言风格选择——先选轴0,再选轴1(就是将二维数组降维分别选择)

""" 过滤 """
print(data.iloc[:, :3][data.three > 5])

4.运算、数据对齐

将两个对象相加时,如果存在某个索引对不相同,则返回结果的索引将是索引对的并集,这类似于索引标签的自动连接(outer join)。

import pandas as pd

s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1], index=['a', 'c', 'e', 'f', 'g'])

""" print("s1:\n", s1, '\n')
print("s2:\n", s2, '\n')
print("s1+s2:\n", s1+s2, '\n') """

data1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'), index=['Ohio', 'Texas', 'Colorado'])
data2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])


print("data1:\n", data1, '\n')
print("data2:\n", data2, '\n')
print("data1+data2:\n", data1+data2, '\n') 

①使用填充值的算术方法

比如当轴标签在一个对象中存在,在另一个对象中不存在时,打算将缺失值填充为0

算术方法:

方法描述
add, radd加法 +
sub, rsub减法 -
div, rdiv除法 /
floordiv, rfloordiv整除 //
mul, rmul乘法 *
pow, rpow幂次方 **
import pandas as pd

df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)), columns=list('abcd'))
df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)), columns=list('abcde'))

# 将 df2 上某位置的值改为NaN
df2.loc[1, 'b'] = np.nan
# 在 df1 上使用add方法,将 df2 和一个fill_value作为参数传入
print(df1.add(df2, fill_value=0))

# 也可以用fill_value传参重建df1的索引
df1.reindex(columns=df2.columns, fill_value=0)

②DataFrame和Series间的操作

广播机制(broadcasting)

import pandas as pd

# 行匹配
arr = np.arange(12.).reshape((3, 4))
print('arr:\n', arr, '\n')
print('arr - arr[0]:\n', arr - arr[0], '\n')

# 列匹配
frame = pd.DataFrame(np.arange(12.).reshape((4, 3)), 
                     columns=list('bde'),
                     index=['Utah', 'Ohio', 'Texas', 'Oregon'])
series = frame.iloc[0]
print('series: \n', series, '\n')
print('frame - series: \n', frame-series, '\n')

# 重建索引——:两数据结构不同时具有某索引标签
series2 = pd.Series(range(3), index=['b', 'e'`,` 'f'])    # frame不具有'e'和'f'索引标签
# 在列上匹配:
series2 = frame['d']
# 在行上广播:
print('frame.sub(series2, axis=\'index\') -> \n', frame.sub(series2, axis='index'))

5.函数应用和映射

import pandas as pd

# NumPy的通用函数(逐元素数组法)对pandas对象也有效
frame = pd.DataFrame(np.random.randn(4, 3), 
                     columns=list('bde'),
                     index=['Utah', 'Ohio', 'Texas', 'Oregon'])
np.abs(frame)   # 将frame中的所有元素都取其绝对值

# 将函数应用到一行或一列的一维数组上
f = lambda x: x.max() - x.min()
frame.apply(f)  # 计算frame的每一列中最大值减去最小值的差值
frame.apply(f, axis='columns')  # 在每列调用后的基础上,在每行都调用一遍 

# 根据frame中的每个浮点数计算一个格式化字符串
formatting = lambda x:'%.2f' % x
frame.applymap(formatting)


6.排序和排名

  • sort_index() 返回一个新的、排序好的对象

  • rank() 通过将平均排名分配到每个组来打破平级的关系,参数如下:

方法描述
average默认:在小组中的平均排名
min对整个组使用最小排名
max对整个组使用最大排名
first按照值在数据中出现的次序分配排名
dense类似于"method=min",但组间排名总是增加1,而不是一个组中的相等元素的数量
import pandas as pd

obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
frame = pd.DataFrame(np.random.randn(4, 3), 
                     columns=list('bde'),
                     index=['Utah', 'Ohio', 'Texas', 'Oregon'])

""" 按轴标签排序 """
print('按轴标签排序-> obj默认按升序排序:\n', obj.sort_index())
# 在各个轴上排序,数据默认升序排序
print('\n按轴标签排序-> frame在轴1按降序排序:\n', frame.sort_index(axis=1, ascending=False))

""" 按值排序 """
print('\n按值排序-> 默认情况下NaN被排序至尾部:\n', obj.sort_values())
# 可以选择多列或一列作为排序键
frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})   # 按数值大小分配排名
print('\n按值排序-> 选择某一列作为排序键:\n', frame.sort_values(by='b'))


""" rank()方法输出排序后的名次 """
obj = pd.Series([7, -5, 7, 4, 2, 0, 4])
print("\n索引:名次\n", obj.rank())
# 将值分配给组中最大排名
obj.rank(ascending=False, method='max')
# DataFrame列排名
frame.rank(axis='columns')

7.含有重复标签的轴索引

  • is_unique() 属性可以告诉你一个Series的标签是否唯一
import pandas as pd

obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
print('obj的索引唯一:', obj.index.is_unique)
print(obj['a'], '\n')     # 无重复索引的返回一个标量值,有重复索引值的返回一个序列

df = pd.DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'c'])
print(df.loc['b'])

三、描述性统计的概述与计算


1.归约方法

可选参数如下:

方法描述
axis归约轴,0为行向,1为列向
skipna排除缺失值,默认为True
level如果轴是多层索引的(MultiIndex),该参数可以缩减分组层级
import pandas as pd

""" 归约型方法 """
df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5],
                   [np.nan, np.nan], [0.75, -1.3]],
                   index=['a', 'b', 'c', 'd'],
                   columns=['one', 'two'])
# 特此提醒:除非整列上都是NaN值,否则输出时NaN值是被自动排除的
print(df.sum(axis=1), '\n')       # 或 axis='columns',将一行上各个列的值相加
# 可以通过禁用 skipna 来实现不排除NaN值
print(df.mean(axis='columns', skipna=False))


2.汇总统计

方法描述
count非Na值的个数
describe计算Series或DataFrame各列的汇总统计集合
min, max计算最小值、最大值
argmin, argmax分别计算最小值、最大值所在的索引位置(整数)
idmin, idmax分别计算最小值或最大值的索引标签
quantile计算样本的从0到1间的分位数
sum加和
mean均值
median中位数(50%分位数)
mad平均值的平均绝对偏差
prod所有值的积
var值的样本方差
std值的样本标准差
skew样本偏度(第三时刻)值
kurt样本峰度(第四时刻)值
cumsum累计值
cummin, cummax累计值得最小值或最大值
cumprod值的累计值
diff计算第一个算术差值(对时间序列有用)
pct_change计算百分比
import pandas as pd
import numpy as np

df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5],
                   [np.nan, np.nan], [0.75, -1.3]],
                   index=['a', 'b', 'c', 'd'],
                   columns=['one', 'two'])
print(df.cumsum())

输出为:

    one  two
a  1.40  NaN
b  8.50 -4.5
c   NaN  NaN
d  9.25 -5.8

3.唯一值、计数和成员属性

方法描述
isin计算表征Series中每个值是否包含于传入序列的布尔值数组中
match计算数组中每个值的整数索引,形成一个唯一值数组。有助于数据对齐和join类型的操作
unique计算Series值中的唯一值数组,按照观察顺序返回
value_counts返回一个Series,索引值是唯一值序列,值是计数个数,按照个数降序排序
import pandas as pd

obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c' ])
uniques = obj.unique()      # 返回唯一值索引标签
print("唯一值索引标签:", uniques, '\n')
print("唯一值索引标签个数:\n", obj.value_counts(), '\n')

# 过滤为值子集
mask = obj.isin(['b', 'c'])
print(mask, '\n')
print("过滤后的值子集为:\n", obj[mask], '\n')

# 将非唯一值数组转换成另一个唯一值数组
print("将非唯一值数组转换成另一个唯一值数组:\n", pd.Index(uniques).get_indexer(obj))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Larissa857

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

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

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

打赏作者

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

抵扣说明:

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

余额充值