暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Pandas入门使用

谭西路 2022-06-11
338

pandas含有使数据清洗和分析工作变得更快更简单地数据结构和操作工具。pandas经常和数值计算工具Numpy和Scipy,以及分析库statsmodels和scikit-learn、数据可视化库matplotlib共同使用。

1. Pandas的数据结构介绍

import pandas as pd
import numpy as np
from pandas import Series, DataFrame

1.1 Series介绍

类似于一维数组地对象,它由一组数据以及与之相关的数据标签(索引)组成。Series的使用主要有:

  • • Series的创建方式

  • • Series的属性

  • • Series的索引、切片、过滤

  • • Series的运算

  • • Series的缺失值检测

# 1. Series的创建,默认标签(索引)是0到len(obj)-1
obj = Series([47, -53])
# 2. Series的创建,指定标签(索引)
obj2 = Series([47, -53], index=['d''b''a''c'])
# 3. 基于字典创建Series,索引默认是字典的键
sdata = {"ohio"3500"Texas":71000"Oregon":16000"Utah":5000}
obj3 = Series(sdata)
# 4. 基于字典创建Series,指定索引,则以指定的索引和字典的键进行左关联
states = ["California""ohio""Oregon""Texas"]
obj4 = Series(sdata, index=states)

# 1. Series的values和index属性
# values返回数组
obj.values
# index返回索引对象
obj2.index
# 2. Series对象本身及其索引都有一个name属性,对其赋值操作
obj4.name = "population"
obj4.index.name = "state"

# 1. 索引、切片、过滤
obj2["a"]
obj2[['c''a''d']]
# 包含末端
obj2["b""c"]
# 不包含末端
obj2[13]
# 布尔过滤
obj2[obj2>0]

# 1. 运算
# 标量乘法
obj2 * 2
# 应用数学函数
np.exp(obj2)
# 两个Series的运算,它将会根据各自的索引标签先进行自动对齐数据,再运算,即做外连接
obj3 + obj4

# 检测缺失值,返回布尔型的Series
pd.isnull(obj4)
pd.notnull(obj4)
obj4.isnull()
obj4.notnull()
# 检测某值是否在索引对象中,即类似字典检测某值是否为键
'b' in obj2
# 修改Series的索引对象,注:索引对象是不可变对象,只能通过重新赋值的方式修改,不能原地修改。
obj.index = ["Bob""Steve""Jeff""Ryan"]

1.2 DataFrame介绍

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型,并且有行索引,也有列索引。DataFrame的介绍使用主要有:

  • • 构建DataFrame的多种方式

  • • DataFrame的行索引和列索引

  • • DataFrame的属性

  • • DataFrame的索引对象

# 1. 由等长列表或numpy数组组成的字典
data = {
    "state": ["Ohio""Ohio""Ohio""Nevada""Nevada""Nevada"],
    "year": [200020012002200120022003],
    "pop": [1.51.73.62.42.93.2]
}
frame = pd.DataFrame(data)

data = {
    "state": np.array(["Ohio""Ohio""Ohio""Nevada""Nevada""Nevada"]),
    "year": np.array([200020012002200120022003]),
    "pop": np.array([1.51.73.62.42.93.2])
}
frame = pd.DataFrame(data)
# 展示若干行,默认是前5行
frame.head()

# 2. 如果指定列序列,那么DataFrame的列就会按照指定顺序排列
pd.DataFrame(data, columns=['year''state''pop'])

# 3. 如果指定的序列在data字典键里面没有,就会在结果中产生缺失值
frame2 = pd.DataFrame(data, columns=["year""state""pop""debt"])

# 4. 同样,指定行索引,如果不指定默认就是 0~n-1
frame2 = pd.DataFrame(data, 
                      columns=["year""state""pop""debt"], 
                      index=['one''two''three''four''five''six'])
# 5. 嵌套字典构建DataFrame
pop = {
    "Nevada":{20012.420022.9},
    "Ohio":{20001.520011.72002:3.6}
}
frame3 = pd.DataFrame(pop)

# 6. 指定行索引,如果指定的行索引不在pop的嵌套字典键中,就会产生缺失值
frame4 = pd.DataFrame(pop, index=[200120022003])

# 7. 利用Series构建DataFrame
pdata = {
    "Ohio": frame3["Ohio"][:-1],
    "Nevada": frame3["Nevada"][:2]
}
pd.DataFrame(pdata)

# 8. 二维数组构建DataFrame
arr = np.array([[123], [456]])
pd.DataFrame(arr, columns=["a""b""c"])

# 1. 获取DataFrame的某列,返回是一个Series
frame2['state'# 方式一
frame2.state    # 方式二,这种方式要保证列名称是一个合理地Python变量名才使用

# 2. 获取DataFrame的某行
frame2.loc["three"]

# 3. 对某一列重新赋值
frame2["debt"] = 16.5
frame2["debt"] = np.arange(6.)
# 如果赋值是一个Series时,会进行对齐操作,
# 以DataFrame的行索引为主,对于Series没有的索引就会被填上缺失值,多余的索引不会关联上
val = pd.Series([1.2, -1.51.7], index=["one""three""ten"])
frame2['debt'] = val
# 若DataFrame中没有该列名称,而被赋值,相当于新增一列,以下新增布尔值得列
frame2["eastern"] = (frame2.state == "Ohio")
frame2

# 4. 删除某一列
del frame2["eastern"]

# 1. DataFrame的index和columns的name属性
frame3.index.name = "year"
frame3.columns.name = "state"

# 2. DataFrame的values属性,以数组形式返回
frame3.values

# 3. DataFrame的装置
frame3.T

# 1. 索引对象,在构建Series或DataFrame时,
# 所用到的任何数组或其他序列的标签都会转换成一个Index
# 注:Index对象是不可变,因此用户不能对其进行修改
obj = pd.Series(range(3), index=['a''b''c'])
obj_index = obj.index
obj_index


frame3.columns
'Nevada' in frame3.columns
2003 in frame3.index

# 注:与Python集合不同,pandas的index可以包含重复的标签
dup_labels = pd.Index(["foo""foo""bar""bar"])
dup_labels

# 2. 索引对象的方法和属性
# 连接另一个index对象,产生一个新的Index对象
obj_index.append(dup_labels)

# 差集: difference
obj_index.difference(dup_labels)

# 交集:intersection
obj_index.intersection(dup_labels)

# 并集
obj_index.union(dup_labels)

# 判断Index对象的每个元素是否都包含在参数集合中
obj_index.isin(["a"])

# 删除传入的值
obj_index.drop("a")

# 删除某位置i处的元素
obj_index.delete(1)

# 将元素插入索引i处
obj_index.insert(1'd')

# 当各元素均大于等于前一个元素时,返回True
obj_index.is_monotonic

# 当Index没有重复值时,返回True
obj_index.is_unique

# 计算Index中唯一值的数组
dup_labels.unique()

2. Pandas的基本功能

  • • 重新索引reindex

  • • 丢弃指定轴上的项

  • • 索引、选取和过滤

  • • 算术运算和数据对齐

  • • 算术方法中填充值

  • • DataFrame和Series之间的运算

  • • 函数应用和映射

  • • 排序和排名

  • • 带有重复标签的轴索引

  • • 汇总和计算描述统计

  • • 相关系数与协方差

  • • 唯一值、值计数以及成员资格

# 重新索引 reindex,作用是创建一个新对象
obj = pd.Series([4.57.2, -5.33.6], index=["d""b""a""c"])

# 1. reindex将会根据新索引进行重排,如果某个索引值在原索引中不存在,就引入缺失值
obj.reindex(["a""b""c""d""e"])

# 2. 重新索引时,需要做一些插值处理,method参数可以实现
obj3 = pd.Series(["blue""purple""yellow"], index=[024])
# 前向值填充
obj3.reindex(range(6), method="ffill")

# 3. DataFrame的重新索引,可以修改行索引和列索引
frame = pd.DataFrame(np.arange(9).reshape(33), 
                     index=["a""c""d"],
                     columns=["Ohio""Texax""California"]
                    )
# 默认是重新行索引,如果原索引没有,引入缺失值
frame.reindex(["a""b""c""d"])
# 重新列索引,方式一
frame.reindex(["Texax""Utah""California"], axis=1)
# 重新列索引,方式二
frame.reindex(columns=["Texax""Utah""California"])

# 4. 引入缺失值时,可以使用替代值,利用fill_value参数
obj.reindex(["a""b""c""d""e"], fill_value=9)

# 填充时的最大填充量,利用limit参数
obj3.reindex(range(8), method="ffill", limit=2)

# 丢弃指定轴的项
obj = pd.Series([4.57.2, -5.33.6], index=["d""b""a""c"])

# 1. 删除Series上的某索引对应的值
obj.drop("c")
obj.drop(["c""d"])
# 就地删除,即再原数据上修改,不复制
obj.drop("c", inplace=True)

# 2. 删除 DataFrame,任意轴上的索引值
data = pd.DataFrame(np.arange(16).reshape((44)),
                    index=["Ohio""Colorado""Utah""NewYork"],
                    columns=["one""two""three""four"]
                   )
# 删除DataFrame的行索引,默认是行索引
data.drop("Utah")
data.drop(["Utah","NewYork"])
data.drop("Utah", axis=0)
# 删除DataFrame的列索引
data.drop("one", axis=1)
data.drop(columns="two")
data.drop(columns=["two""three"])
data.drop("one", axis=1, inplace=True)

# 索引、选取和过滤
# 1. Series索引实例
obj = pd.Series(np.arange(4.), index=["a""b""c""d"])
obj["b"]
obj[1]
obj[2:3# 不包含末端
obj["a""c"# 包含末端
obj[["b""a""d"]]
obj[[132]]
# 过滤
obj[obj<2]
# 赋值
obj["a""c"] = 10
obj["e"] = 20


# 2. DataFrame索引实例
data = pd.DataFrame(np.arange(16).reshape((44)), 
                    index=["Ohio""Colorado""Utah""New York"],
                    columns=["one""two""three""four"]
                   )
# 列索引
data["two"]
data[["three""one"]]

# 切片方式选取数据,以下是行索引
data[:2]

# 布尔型数组选取数据, 只要布尔数组的一行全是false,才会被过滤掉
data[data["three"] > 5]

# 布尔型数组指定为True的位置进行赋值操作
data[data<5] = 0

# 3. 用loc和iloc进行选取操作
# loc是使用轴标签选取
data.loc["Colorado"]
data.loc["Colorado", ["two""three"]]
data.loc[["Ohio""Utah"], ["one""four"]]
data.loc["Ohio""Utah""one""three"]  # 切片包含末端

# iloc使用整数索引选取
data.iloc[2]
data.iloc[2, [301]]
data.iloc[123]  # 切片不包含末端
data.iloc[:, [12]]
data.iloc[[12], :]

# 4. 获取DataFrame的单一标量
# at使用轴标签选取单一标量
data.at["Utah""three"# 返回10

# iat使用整数索引选取单一标量
data.iat[20]  # 返回8

# 注: 若标签索引 是含有整数,那么使用整数索引时,会引起歧义。
# pandas为了统一,如果轴索引含有整数,数据选取总会使用标签
# 为了更准确,请使用loc(标签)或 iloc(整数)

ser2 = pd.Series([345], index=[123])
ser2[3# 优先标签索引,返回5
ser2[12# 切片优先整数索引,不包含末端,返回4,
# 建议歧义情况,容易混乱,就用loc或iloc
ser2.loc[12]
ser2.iloc[12]

# 1. 算术运算和数据对齐
s1 = pd.Series([7.3, -2.53.41.5], index=["a""c""d""e"])
s2 = pd.Series([-2.13.6, -1.543.1], index=["a""c""e""f""g"])
# 两个Series相加将进行对齐操作,不能重叠的索引,引入NA值
s1+s2

df1 = pd.DataFrame(np.arange(9.0).reshape(33), 
                   index=["Ohio""Texas""Colorado"],
                   columns=["b""c""d"])
df2 = pd.DataFrame(np.arange(12).reshape(43),
                   index=["Utah""Ohio""Texas""Oregon"],
                   columns=["b""d""e"]
                  )
# 两个DataFrame相加,将基于共同的行和列标签进行对齐相加,没有的话,都会引入NA值
df1 + df2

# 2. 在算术方法中填充值,注意若df1.add(df2),那么只会填充df1的没有重叠的行标签和列标签,
# 即df2的没有重叠的行Oregon、Utah和列e都不会填充
df1.add(df2, fill_value=0)

# DataFrame和Series之间的运算
frame = pd.DataFrame(np.arange(12.).reshape((43)),
                   columns=list("bde"),
                   index=["Utah""Ohio""Texas""Oregon"]
                  )
series = frame.iloc[0]
frame - series  # 沿着行进行广播

series2 = frame.iloc[:, 0]
# 若希望沿着列进行广播
frame.sub(series2, axis=0)

# 若某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象会被重新索引形成并集
series3 = pd.Series(range(3), index=["b""d""f"])
frame + series3

# 函数应用和映射
frame = pd.DataFrame(np.arange(12.).reshape((43)),
                   columns=list("bde"),
                   index=["Utah""Ohio""Texas""Oregon"]
                  )
# 1. 函数应用
np.abs(frame)

# 2. 映射
# 默认是轴0上操作,即DataFrame每列上
frame.apply(lambda x: x.max() - x.min())
# 若希望轴1上操作,即DataFrame每行上,axis=1,或axis="columns"
frame.apply(lambda x: x.max() - x.min(), axis=1)

# 传递到apply的函数不是必须返回一个标量,还可返回由多个多个值组成的Series
def f(x):
    return pd.Series([x.min(), x.max()], index=["min""max"])

frame.apply(f)

# 3. 以上映射都是基于每列或每行的元素做映射,如果想单个元素做映射呢?
frame.applymap(lambda x: "%.2f" % x)
# 对于Series,和applymap一样的功能,用于元素级的函数是map
frame['e'].map(lambda x: "%.2f" % x)

# 排序和排名
obj = pd.Series([4213], index=["d""a""b""c"])
# 1. sort_index方法对索引进行排序,返回一个已排序的新对象
obj.sort_index()
# 2. sort_values 对值进行排序
obj.sort_values()

frame = pd.DataFrame(np.arange(8).reshape(24),
                     index=["three""one"],
                     columns=["d""a""b""c"]
                    )
# 3. DataFrame 默认是对行索引进行排序,且是按升序排序
frame.sort_index()
frame.sort_index(axis=1)
frame.sort_index(axis=1, ascending=False)

# 4. DataFrame 对值进行排序,默认是轴0
frame.sort_values(by='b')
frame.sort_values(by=['b'"c"])

frame.sort_values(by="three", axis=1)

# 5. 排名
obj = pd.Series([7, -574204])
# rank是通过为各组分配一个平均排名的方式破坏评级关系的,即一样的值,排名是他们的均值,如:7的排名是6.5

obj.rank()
# 也可以根据原数据出现的顺序给出排名
obj.rank(method="first")
# 按照降序排名
obj.rank(ascending=False, method="max")

# DataFrame的排名
frame = pd.DataFrame({"b":[4.37, -32],
                     "c": [-258, -2.5]})
frame.rank(axis=0)

# 重复标签的轴索引
obj = pd.Series(range(5), index=["a""a""b""b""c"])
obj.index.is_unique  # 返回False
obj["a"]

# 汇总和计算描述统计
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"]
                 )
# 注:默认NA值会自动排除,除非整个切片都是NA
df.sum()
df.mean()
# 注:第三行全是nan值,求和后默认为0
df.sum(axis=1)
# 注:使用 skipna=False,NA值不会自动排除
df.sum(axis=1, skipna=False)


# idxmax和idxmin 返回间接统计,最大/小值的索引
df.idxmax()  # one列返回索引b, two列返回索引d

# 累计型的方法,如:cumsum, cummin, cummax
df.cumsum()

# 一次性产生多个汇总统计
df.describe()

# 相关系数与协方差
# 这里简单说几个函数:
#  相关系数:corr()
#  协方差:   cov()
# 使用示例:df.corr()、series1.corr(series2)

# 唯一值、值计数以及成员资格
obj = pd.Series(["c""a""d""a""a""b""c""c""b"])
# 1. 唯一值
uniques = obj.unique()
uniques

# 2. 计算各值出现的频率
obj.value_counts()   # 默认按值频率的降序排列
pd.value_counts(obj.values, sort=False# 取消排序

# 3. isin用于判断矢量化集合的成员资格
mask = obj.isin(["b""c"])
obj[mask]

# 4. 与isin类似,给一个索引数组对象,判断obj的各元素是否在索引数组对象中,
# 若在返回其在索引对象元素中位置,不在返回-1。
pd.Index(["a""c"]).get_indexer(obj) # 返回 array([ 1,  0, -1,  0,  0, -1,  1,  1, -1])

# 5. DataFrame的各个列的取值的统计
# 结果中行标签是所有列的唯一值,每个列中这些值是相应的计数。
data = pd.DataFrame({"Qu1": ["a""b""c""a""b"], "Qu2": ["b""c""e""e""e"]})
data.apply(pd.value_counts).fillna(0)


后记:

更新的速度很慢,但我相信未来我的原创文章会越来越多的,因为开始走了第一步,接下来只要慢慢去做,坚持去做就好了。这只是开始,写的东西都很简单,一本书可能很快就能看完,但却记不住,只有用起来,才能熟能生巧,运用其如,有机会准备写个Pandas的实战系列,搞几个小案例,到时它的作用就一目了然。

文章转载自谭西路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论