Pandas
Pandas 是一个开源的 Python 数据分析库,它提供了高性能、易用的数据结构和数据分析工具。Pandas 的设计理念是让数据处理和分析工作在 Python 中变得更加容易。以下是 Pandas 的一些关键特性:
数据结构
Series:一维数组,类似于 Python 的列表,但是每个元素都有一个索引。
DataFrame:二维表格结构,类似于 Excel 或 SQL 表,每列可以是不同的数据类型。
Panel:三维数组,较少使用,主要在处理多维度数据时使用。
常用功能
数据导入:支持多种数据格式,如 CSV、Excel、SQL、HDF5 等。
数据清洗:缺失值处理、重复值处理、数据类型转换等。
数据筛选:基于条件筛选数据。
数据分组:类似于 SQL 的分组功能,支持聚合、转换等操作。
数据合并:支持多种方式的合并(merge)、连接(join)操作。
时间序列处理:提供强大的时间序列处理功能。
文本数据处理:字符串操作、正则表达式等。
数据类型 Series
Series:一维数组。
import pandas as pd
s = pd.Series([2,3,5,7,11],name='A')
s
0 2
1 3
2 5
3 7
4 11
Name: A, dtype: int64
# 以时间为索引的Seriesdts1 = pd.DatetimeIndex(['2024-01-01 00:00:00','2024-01-01 03:00:00','2024-01-01 06:00:00'])
dts1
DatetimeIndex(['2024-01-01 00:00:00', '2024-01-01 03:00:00','2024-01-01 06:00:00'],dtype='datetime64[ns]', freq=None)
# 另一种写法 pd.date_range可以按一定的频率生成时间序列dts2 = pd.date_range(start = '2024-01-01',periods=6,freq='3H')
dts2
DatetimeIndex(['2024-01-01 00:00:00', '2024-01-01 03:00:00','2024-01-01 06:00:00', '2024-01-01 09:00:00','2024-01-01 12:00:00', '2024-01-01 15:00:00'],dtype='datetime64[ns]', freq='3H')
dts3 = pd.date_range('2024-01-01',periods=6,freq='d')
dts3
DatetimeIndex(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04','2024-01-05', '2024-01-06'],dtype='datetime64[ns]', freq='D')
数据类型 DataFrame
DataFrame:二维的表格数据结构,可以理解为Series的容器,既有行索引,又有列索引。
# 从字典 创建DataFrame
d = {'A':[1,2,3],'B':[4,5,6],'C':[7,8,9]}df = pd.DataFrame(data=d)
df
# 从列表创建DataFrame
d = [[4,7,10],[5,8,11],[6,9,11]]df1 = pd.DataFrame(data=d,index=['a','b','c'],columns=["A","B","C"]
)df1
# 从数组创建DataFrame# 数组(array)
import numpy as np
d = np.array([[1,2,3],[4,5,6],[7,8,9]])
df2 = pd.DataFrame(data = d,index=["a","b","c"],columns=["A","B","C"]
)
df2
数据查看
import numpy as np
import pandas as pd
d = np.array([[81,2,34,99],[7,4,5,6],[8,9,5,11],[89,3,5,8],[9,2,34,9]])
df = pd.DataFrame(data =d,columns=list("abcd"))
df
| a | b | c | d |
---|
0 | 81 | 2 | 34 | 99 |
---|
1 | 7 | 4 | 5 | 6 |
---|
2 | 8 | 9 | 5 | 11 |
---|
3 | 89 | 3 | 5 | 8 |
---|
4 | 9 | 2 | 34 | 9 |
# 查看前几行
df.head(2)
# 查看后几行
df.tail(2)
# 随机查看几行
df.sample(2)
# 按列选取
df["a"]
0 81
1 7
2 8
3 89
4 9
Name: a, dtype: int32
条件查询
d = np.array([[81,2,34,99],[7,4,5,6],[8,9,5,11],[89,3,5,8],[9,2,34,9]])
df = pd.DataFrame(data =d,columns=list("abcd"))
df
| a | b | c | d |
---|
0 | 81 | 2 | 34 | 99 |
---|
1 | 7 | 4 | 5 | 6 |
---|
2 | 8 | 9 | 5 | 11 |
---|
3 | 89 | 3 | 5 | 8 |
---|
4 | 9 | 2 | 34 | 9 |
# 单一条件
df[df["a"]>60]
df.loc[df["a"]>60]
# 单一条件 & 多列
df.loc[df["a"]>60,["a","b","d"]]
# 多条件
df[(df["a"]>20) & (df["b"]>1)]
# 多条件筛选行 & 指定列筛选列
df.loc[(df["a"]>60)&(df["b"]>2),["a","b","d"]]
# 多条件筛选行 & 指定列筛选列
df.loc[(df["a"]>60)&(df["b"]>3),["a","b","d"]]
数学计算
import pandas as pd
import numpy as np
d = np.array([[81,28,24,25,96],[8,35,56,98,39],[13,39,55,36,3],[70,54,69,48,12],[63,80,97,25,70]])
df =pd.DataFrame(data=d,columns=list("abcde"))
df
| a | b | c | d | e |
---|
0 | 81 | 28 | 24 | 25 | 96 |
---|
1 | 8 | 35 | 56 | 98 | 39 |
---|
2 | 13 | 39 | 55 | 36 | 3 |
---|
3 | 70 | 54 | 69 | 48 | 12 |
---|
4 | 63 | 80 | 97 | 25 | 70 |
聚合计算
聚合计算:是指对数据进行汇总和统计的操作。常用的聚合计算方法包括计算均值、求和、最大值、最小值、计数等。
df["a"].mean()
47.0
df["a"].sum()
235
df["a"].max()
81
df["a"].min()
8
df["a"].count()
5
df["a"].median() # 中位数
63.0
df["a"].var() # 方差
1154.5
df["a"].skew() # 偏度
-0.45733193928530436
df["a"].kurt() # 峰度
-2.9999915595685325
df["a"].cumsum() # 累计求和
0 81
1 89
2 102
3 172
4 235
Name: a, dtype: int32
df["a"].cumprod() # 累计求积
0 81
1 648
2 8424
3 589680
4 37149840
Name: a, dtype: int32
df["a"].diff() # 差分
0 NaN
1 -73.0
2 5.0
3 57.0
4 -7.0
Name: a, dtype: float64
df["a"].mad() # 平均绝对值
29.2
按行、列聚合计算
df.sum(axis=0) # 按列汇总求和
a 235
b 236
c 301
d 232
e 220
dtype: int64
df.sum(axis=1) # 按行汇总求和
0 254
1 236
2 146
3 253
4 335
dtype: int64
df.describe() # 描述性统计
| a | b | c | d | e |
---|
count | 5.000000 | 5.000000 | 5.000000 | 5.000000 | 5.000000 |
---|
mean | 47.000000 | 47.200000 | 60.200000 | 46.400000 | 44.000000 |
---|
std | 33.977934 | 20.656718 | 26.395075 | 30.369392 | 39.083244 |
---|
min | 8.000000 | 28.000000 | 24.000000 | 25.000000 | 3.000000 |
---|
25% | 13.000000 | 35.000000 | 55.000000 | 25.000000 | 12.000000 |
---|
50% | 63.000000 | 39.000000 | 56.000000 | 36.000000 | 39.000000 |
---|
75% | 70.000000 | 54.000000 | 69.000000 | 48.000000 | 70.000000 |
---|
max | 81.000000 | 80.000000 | 97.000000 | 98.000000 | 96.000000 |
agg函数
对整个DataFrame批量使用多个聚合函数
df.agg(["sum","mean","max","min","median"]) # 默认按照列
| a | b | c | d | e |
---|
sum | 235.0 | 236.0 | 301.0 | 232.0 | 220.0 |
---|
mean | 47.0 | 47.2 | 60.2 | 46.4 | 44.0 |
---|
max | 81.0 | 80.0 | 97.0 | 98.0 | 96.0 |
---|
min | 8.0 | 28.0 | 24.0 | 25.0 | 3.0 |
---|
median | 63.0 | 39.0 | 56.0 | 36.0 | 39.0 |
df.agg(["sum","mean","max","min","median"],axis=1)
| sum | mean | max | min | median |
---|
0 | 254.0 | 50.8 | 96.0 | 24.0 | 28.0 |
---|
1 | 236.0 | 47.2 | 98.0 | 8.0 | 39.0 |
---|
2 | 146.0 | 29.2 | 55.0 | 3.0 | 36.0 |
---|
3 | 253.0 | 50.6 | 70.0 | 12.0 | 54.0 |
---|
4 | 335.0 | 67.0 | 97.0 | 25.0 | 70.0 |
对DataFrame的某些列应用不同的聚合函数
df.agg({"a":["max","min"],"b":["sum","mean"],"c":["median"]})
| a | b | c |
---|
max | 81.0 | NaN | NaN |
---|
min | 8.0 | NaN | NaN |
---|
sum | NaN | 236.0 | NaN |
---|
mean | NaN | 47.2 | NaN |
---|
median | NaN | NaN | 56.0 |
apply、applymap、map函数
注:applymap函数在新版已被弃用,这里的案例是基于pandas==1.3.2写的
在Python 中如果想要对数据使用函数,可以借助apply(),applymap(),map()对数据进行转换,括号里面可以是直接函数式,或者自定义函数(def)或者匿名函数(lambda)
1、当我们要对数据框(DataFrame)的数据进行按行或按列操作时用apply()
df.apply(lambda x:x.max()-x.min(),axis=1) # axis=1 对行数据进行操作
0 72
1 90
2 52
3 58
4 72
dtype: int64
df.apply(lambda x:x.max()-x.min(),axis=0) # axis=0 对列数据进行操作
a 73
b 52
c 73
d 73
e 93
dtype: int64
2、当我们要对数据框(DataFrame)的每一个数据进行操作时用applymap(),返回结果是DataFrame格式
df.applymap(lambda x:1 if x>60 else 0) # applymap() 对每一个数据进行操作
| a | b | c | d | e |
---|
0 | 1 | 0 | 0 | 0 | 1 |
---|
1 | 0 | 0 | 0 | 1 | 0 |
---|
2 | 0 | 0 | 0 | 0 | 0 |
---|
3 | 1 | 0 | 1 | 0 | 0 |
---|
4 | 1 | 1 | 1 | 0 | 1 |
3、当我们要对Series的每一个数据进行操作时用map()
df["a"].map(lambda x : 1 if x >60 else 0)
0 1
1 0
2 0
3 1
4 1
Name: a, dtype: int64
总结
apply() 函数可以在DataFrame或Series上用自定义函数,可以在行或者列上进行操作。
applymap()函数只适用于DataFrame,可以在每个元素上应用自定义函数。
map()函数只适用于Series,用于将每个元素映射到另一个值。
pandas合并连接
在pandas中,有很多种方法可以合并和拼接数据。常见的方法包括:append()、concat()、merge()。
追加(Append)
append()函数用于将一个DataFrame或Series对象追加到另一个DataFrame中。
import pandas as pd
df1 = pd.DataFrame({"A":["a","b"],"B":[1,2]
})
df1
df2 = pd.DataFrame({"A":["b","c","d"],"B":[2,3,4]
})
df2
df1.append(df2,ignore_index=True)
C:\Users\Alwen\AppData\Local\Temp\ipykernel_2976\2717680053.py:1: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.df1.append(df2,ignore_index=True)
合并(Concat)
concat()函数用于沿指定轴将多个对象(比如Series、DataFrame)堆叠在一起。可以沿行或列方向进行拼接。
# 上下堆叠的例子
df1 = pd.DataFrame({"A":["a","b"],"B":[1,2]
})
df1
df2 = pd.DataFrame({"A":["b","c","d"],"B":[2,3,4]
})
df2
pd.concat([df1,df2],axis=0) # 上下拼接 按照列进行拼接
# 左右堆叠的列子
df1 = pd.DataFrame({"A":["a","b"]})
df1
df2 = pd.DataFrame({"B":[1,2],"C":[3,4]
})
df2
pd.concat([df1,df2],axis=1) # 左右拼接 按照行拼接
连接(Merge)
merge()函数用于根据一个或多个键将两个DataFrame的行连接起来。类似SQL中的JOIN操作。
数据连接1(pd.merge)
inner 和 outer连接
df1 = pd.DataFrame({"A":["a","b","c"],"B":[1,2,3]
})
df1
df2 = pd.DataFrame({"A":["b","c","d"],"B":[2,3,4]
})
df2
pd.merge(df1,df2,how="inner")
pd.merge(df1,df2,how="outer")
数据连接2(pd.merge)
左右连接 left right
df1 = pd.DataFrame({"A":["a","b","c"],"B":[1,2,3]
})
df1
df2 = pd.DataFrame({"A":["b","c","d"],"C":[2,3,4]
})
df2
pd.merge(df1,df2,how = "left",on="A") # 左连接
pd.merge(df1,df2,how="right",on="A") # 右连接
pd.merge(df1,df2,how="inner",on="A") # 内连接
pd.merge(df1,df2,how="outer",on = "A") # 外连接
| A | B | C |
---|
0 | a | 1.0 | NaN |
---|
1 | b | 2.0 | 2.0 |
---|
2 | c | 3.0 | 3.0 |
---|
3 | d | NaN | 4.0 |
补充1个小技巧
df1[df1["A"].isin(df2["A"])] # 返回在df1中列"A"的值在df2中国也存在的行
df1[~df1["A"].isin(df2["A"])] # 返回在df1中列"A"的值在df2中不存在的行
pandas分组聚合
分组聚合(group by)顾名思义就是分2步:
1.先分组:根据某列数据的值进行分组。用groupby()对某列进行分组。
2.后聚合:将结果应用聚合函数进行计算。在agg()函数里应用聚合函数被计算结果。如:sum()、mean()、count()、max()、min()等,用于对每个分组进行聚合计算。
import pandas as pd
import numpy as np
import random
df = pd.DataFrame({"A":["a","b","a","b","a","b"],"B":["L","L","M","N","M","M"],"C":[107,177,139,3,52,38],"D":[22,59,38,50,60,82]
})
df
| A | B | C | D |
---|
0 | a | L | 107 | 22 |
---|
1 | b | L | 177 | 59 |
---|
2 | a | M | 139 | 38 |
---|
3 | b | N | 3 | 50 |
---|
4 | a | M | 52 | 60 |
---|
5 | b | M | 38 | 82 |
单列分组
1.对单列分组后应用sum聚合函数
df.groupby("A").sum()
2.对单列分组后应用单个指定的聚合函数
df.groupby("A").agg({"C":"min",}).rename(columns={"C":"C_min"})
3.对单列分组后应用多个指定的聚合函数
df.groupby("A").agg({"C":"max","D":"min"}).rename(columns={"C":"C_max","D":"D_min"})
两列分组
1.对多列分组后应用sum聚合函数
df.groupby(["A","B"]).sum()
| | C | D |
---|
A | B | | |
---|
a | L | 107 | 22 |
---|
M | 191 | 98 |
---|
b | L | 177 | 59 |
---|
M | 38 | 82 |
---|
N | 3 | 50 |
2.对两列进行group后,都应用max聚合函数
df.groupby(["A","B"]).agg({"C":"max"}).rename(columns={"C":"C_max"})
| | C_max |
---|
A | B | |
---|
a | L | 107 |
---|
M | 139 |
---|
b | L | 177 |
---|
M | 38 |
---|
N | 3 |
3.对两列进行分组group后,应用max、min聚合函数。
df.groupby(["A","B"]).agg({"C":"max","D":"min"}).rename(columns={"C":"C_MAX","D":"D_MIN"})
| | C_MAX | D_MIN |
---|
A | B | | |
---|
a | L | 107 | 22 |
---|
M | 139 | 38 |
---|
b | L | 177 | 59 |
---|
M | 38 | 82 |
---|
N | 3 | 50 |
补充1:应用自定义的聚合函数
df = pd.DataFrame({"A":["a","b","a","b","a","b"],"B":["L","L","M","N","M","M"],"C":[107,177,139,3,52,38],"D":[22,59,38,50,60,82]
})
df
| A | B | C | D |
---|
0 | a | L | 107 | 22 |
---|
1 | b | L | 177 | 59 |
---|
2 | a | M | 139 | 38 |
---|
3 | b | N | 3 | 50 |
---|
4 | a | M | 52 | 60 |
---|
5 | b | M | 38 | 82 |
## 使用自定义的聚合函数计算每个分组的最大值和最小值
def custom_agg(x):return x.max() - x.min()result = df[["B","C"]].groupby("B").agg({"C":custom_agg})
result
补充2:开窗函数(类似于SQL里面的over partition by):
使用transform函数计算每个分组的均值
# 使用transform函数计算每个分组的均值
df["B_C_std"] = df[["B","C"]].groupby("B")["C"].transform("mean")
df
| A | B | C | D | B_C_std |
---|
0 | a | L | 107 | 22 | 142.000000 |
---|
1 | b | L | 177 | 59 | 142.000000 |
---|
2 | a | M | 139 | 38 | 76.333333 |
---|
3 | b | N | 3 | 50 | 3.000000 |
---|
4 | a | M | 52 | 60 | 76.333333 |
---|
5 | b | M | 38 | 82 | 76.333333 |
补充3:分组聚合拼接字符串pandas实现类似group_concat功能
df = pd.DataFrame({"姓名":["张三","张三","张三","李四","李四","李四"],"科目":["语文","数学","英语","语文","数学","英语"]
})
df
| 姓名 | 科目 |
---|
0 | 张三 | 语文 |
---|
1 | 张三 | 数学 |
---|
2 | 张三 | 英语 |
---|
3 | 李四 | 语文 |
---|
4 | 李四 | 数学 |
---|
5 | 李四 | 英语 |
补充:按某列分组,将另一列文本拼接合并
按名称分组,把每个人的科目拼接到一个字符串
# 对整个group对象中的所有列应用join连接元素
(df.astype(str) # # 先将数据全转为字符
.groupby("姓名") #分组
.agg(lambda x : ",".join(x)))[["科目"]] # join 连接元素
pandas 数据重塑
数据重塑,顾名思义就是给数据做各种变形,主要有以下几种:
1.df.pivot 数据变形
2.df.pivot_table 数据透视表
3.df.stack/unstack 数据堆叠
4.df.melt 数据融合
5.df.cross 数据交叉表
df.pivot 数据变形
根据索引(index)、列(column)(values)值,对原有DataFrame(数据框)进行变形重塑,俗称长表转宽表
import pandas as pd
import numpy as np
df = pd.DataFrame({"姓名":["张三","张三","张三","李四","李四","李四"],"科目":["语文","数学","英语","语文","数学","英语"],"成绩":[91,80,100,80,100,96]
})
df
| 姓名 | 科目 | 成绩 |
---|
0 | 张三 | 语文 | 91 |
---|
1 | 张三 | 数学 | 80 |
---|
2 | 张三 | 英语 | 100 |
---|
3 | 李四 | 语文 | 80 |
---|
4 | 李四 | 数学 | 100 |
---|
5 | 李四 | 英语 | 96 |
# 长转宽:使用df.pivot以姓名为index,以各科目为columns,来统计各科成绩:df.pivot(index = "姓名",columns="科目",values="成绩")
科目 | 数学 | 英语 | 语文 |
---|
姓名 | | | |
---|
张三 | 80 | 100 | 91 |
---|
李四 | 100 | 96 | 80 |
pd.melt() 数据融合
df1 = pd.pivot(df,index="姓名",columns="科目",values="成绩").reset_index()
df1
科目 | 姓名 | 数学 | 英语 | 语文 |
---|
0 | 张三 | 80 | 100 | 91 |
---|
1 | 李四 | 100 | 96 | 80 |
# 宽表变长表:使用pd.melt以姓名为标识变量的列id_var,以各科目为value_vars,来统计各科成绩df1.melt(id_vars=["姓名"],value_vars=["语文","数学","英语"])
| 姓名 | 科目 | value |
---|
0 | 张三 | 语文 | 91 |
---|
1 | 李四 | 语文 | 80 |
---|
2 | 张三 | 数学 | 80 |
---|
3 | 李四 | 数学 | 100 |
---|
4 | 张三 | 英语 | 100 |
---|
5 | 李四 | 英语 | 96 |
pd.pivot_table() 数据透视表
import random
random.seed(1024)
df = pd.DataFrame({"专业":np.repeat(["数学与应用数学","计算机","统计学"],4),"班级":["1班","1班","2班","2班"]*3,"科目":["高数","线代"]*6,"平均分":[random.randint(60,100) for i in range(12)],"及格人数":[random.randint(30,50) for i in range(12)]
})
df
| 专业 | 班级 | 科目 | 平均分 | 及格人数 |
---|
0 | 数学与应用数学 | 1班 | 高数 | 85 | 33 |
---|
1 | 数学与应用数学 | 1班 | 线代 | 62 | 43 |
---|
2 | 数学与应用数学 | 2班 | 高数 | 95 | 50 |
---|
3 | 数学与应用数学 | 2班 | 线代 | 87 | 40 |
---|
4 | 计算机 | 1班 | 高数 | 61 | 50 |
---|
5 | 计算机 | 1班 | 线代 | 72 | 44 |
---|
6 | 计算机 | 2班 | 高数 | 100 | 45 |
---|
7 | 计算机 | 2班 | 线代 | 60 | 32 |
---|
8 | 统计学 | 1班 | 高数 | 74 | 49 |
---|
9 | 统计学 | 1班 | 线代 | 66 | 36 |
---|
10 | 统计学 | 2班 | 高数 | 75 | 46 |
---|
11 | 统计学 | 2班 | 线代 | 99 | 39 |
各个专业对应科目的及格人数和平均分
pd.pivot_table(df,index =["专业","科目"],values = ["及格人数","平均分"],aggfunc={"及格人数":np.sum,"平均分":"mean"})
| | 及格人数 | 平均分 |
---|
专业 | 科目 | | |
---|
数学与应用数学 | 线代 | 83 | 74.5 |
---|
高数 | 83 | 90.0 |
---|
统计学 | 线代 | 75 | 82.5 |
---|
高数 | 95 | 74.5 |
---|
计算机 | 线代 | 76 | 66.0 |
---|
高数 | 95 | 80.5 |
补充说明
df.pivot_table()和df.pivot()都是Pandas中用于将长表转换为宽表的方法,但是它们在使用方式和功能上有一些区别。
1.使用方式:
df.pivot()方法接受三个参数:index、columns和values,分别指定新表的索引、列和值。
df.pivot_table()方法接受多个参数,其中最重要的是index、columns和values,用于指定新表的索引、列和值。此外,还可以使用aggfunc参数指定对重复值进行聚合操作的函数,默认为均值。
2.处理重复值:
df.pivot()方法在长表中存在重复值时会引发错误。因此,如果长表中存在重复值,就需要先进行去重操作,或者使用其他方法来处理重复值。
df.pivot_table()方法可以在长表中存在重复值的情况下进行透视操作,并可以使用aggfunc参数指定对重复值进行聚合操作的函数,默认为均值。
3.聚合操作:
df.pivot()方法不支持对重复值进行聚合操作,它只是简单地将长表中的数据转换为宽表。
df.pivot_table()方法支持对重复值进行聚合操作。可以使用aggfunc参数来指定聚合函数,例如求均值、求和、计数等。
总的来说,df.pivot()方法适用于长表中不存在重复值的情况,而df.pivot_table()方法适用于长表中存在重复值的情况,并且可以对重复值进行聚合操作。根据具体的数据结构和分析需求,选择合适的方法进行转换操作。
数据堆叠(Stack/Unstack)
import pandas as pd
import numpy as np
import random
df = pd.DataFrame({"专业":np.repeat(["数学与应用数学","计算机","统计学","物理学"],6),"班级":["1班","2班","3班"]*8,"科目":["高数","线代"]*12,"平均分":[random.randint(60,100) for i in range(24)],"及格人数":[random.randint(30,50) for i in range(24)]})
df2 = pd.pivot_table(df,index=["专业","科目"],values = ["及格人数","平均分"],aggfunc={"及格人数":np.sum , "平均分":np.mean})
df2
| | 及格人数 | 平均分 |
---|
专业 | 科目 | | |
---|
数学与应用数学 | 线代 | 106 | 82.333333 |
---|
高数 | 105 | 81.333333 |
---|
物理学 | 线代 | 132 | 84.666667 |
---|
高数 | 119 | 87.666667 |
---|
统计学 | 线代 | 110 | 84.000000 |
---|
高数 | 115 | 85.333333 |
---|
计算机 | 线代 | 121 | 85.333333 |
---|
高数 | 109 | 84.666667 |
stacked = df2.stack()
专业 科目
数学与应用数学 线代 及格人数 106.000000平均分 82.333333高数 及格人数 105.000000平均分 81.333333
物理学 线代 及格人数 132.000000平均分 84.666667高数 及格人数 119.000000平均分 87.666667
统计学 线代 及格人数 110.000000平均分 84.000000高数 及格人数 115.000000平均分 85.333333
计算机 线代 及格人数 121.000000平均分 85.333333高数 及格人数 109.000000平均分 84.666667
dtype: float64
“压缩”后的DataFrame或Series(具有MultiIndex作为索引),stack()的逆操作是unstack(),默认情况下取消最后压缩的那个级别:堆叠stack(),顾名思义就是把透视结果到一起。接下来我们把透视后堆叠的数据一步步展开unstack():
stacked.unstack()
| | 及格人数 | 平均分 |
---|
专业 | 科目 | | |
---|
数学与应用数学 | 线代 | 106.0 | 82.333333 |
---|
高数 | 105.0 | 81.333333 |
---|
物理学 | 线代 | 132.0 | 84.666667 |
---|
高数 | 119.0 | 87.666667 |
---|
统计学 | 线代 | 110.0 | 84.000000 |
---|
高数 | 115.0 | 85.333333 |
---|
计算机 | 线代 | 121.0 | 85.333333 |
---|
高数 | 109.0 | 84.666667 |
stacked.unstack(level=1)
| 科目 | 线代 | 高数 |
---|
专业 | | | |
---|
数学与应用数学 | 及格人数 | 106.000000 | 105.000000 |
---|
平均分 | 82.333333 | 81.333333 |
---|
物理学 | 及格人数 | 132.000000 | 119.000000 |
---|
平均分 | 84.666667 | 87.666667 |
---|
统计学 | 及格人数 | 110.000000 | 115.000000 |
---|
平均分 | 84.000000 | 85.333333 |
---|
计算机 | 及格人数 | 121.000000 | 109.000000 |
---|
平均分 | 85.333333 | 84.666667 |
stacked.unstack(level=0)
| 专业 | 数学与应用数学 | 物理学 | 统计学 | 计算机 |
---|
科目 | | | | | |
---|
线代 | 及格人数 | 106.000000 | 132.000000 | 110.000000 | 121.000000 |
---|
平均分 | 82.333333 | 84.666667 | 84.000000 | 85.333333 |
---|
高数 | 及格人数 | 105.000000 | 119.000000 | 115.000000 | 109.000000 |
---|
平均分 | 81.333333 | 87.666667 | 85.333333 | 84.666667 |
数据交叉表(pd.crosstab)
交叉表显示了每个变量的不同类别组合中观察到的频率或计数。通俗的说,就是根据不同列的数据统计了频数。
df = pd.DataFrame({"High":["高","高","高","中","中","中","低","低","低","高","低"],"Weight":["重","轻","中","中","轻","重","重","轻","中","重","轻"]
})
df
| High | Weight |
---|
0 | 高 | 重 |
---|
1 | 高 | 轻 |
---|
2 | 高 | 中 |
---|
3 | 中 | 中 |
---|
4 | 中 | 轻 |
---|
5 | 中 | 重 |
---|
6 | 低 | 重 |
---|
7 | 低 | 轻 |
---|
8 | 低 | 中 |
---|
9 | 高 | 重 |
---|
10 | 低 | 轻 |
pd.crosstab(df["High"],df["Weight"])
Weight | 中 | 轻 | 重 |
---|
High | | | |
---|
中 | 1 | 1 | 1 |
---|
低 | 1 | 2 | 1 |
---|
高 | 1 | 1 | 2 |
双层crosstab
df = pd.DataFrame({"High":["高","高","高","中","中","中","低","低","低","高","低"],"Weight":["重","轻","中","中","轻","重","重","轻","中","重","轻"],"Size":["大","中","小","中","中","大","中","小","小","大","小"]
})
df
| High | Weight | Size |
---|
0 | 高 | 重 | 大 |
---|
1 | 高 | 轻 | 中 |
---|
2 | 高 | 中 | 小 |
---|
3 | 中 | 中 | 中 |
---|
4 | 中 | 轻 | 中 |
---|
5 | 中 | 重 | 大 |
---|
6 | 低 | 重 | 中 |
---|
7 | 低 | 轻 | 小 |
---|
8 | 低 | 中 | 小 |
---|
9 | 高 | 重 | 大 |
---|
10 | 低 | 轻 | 小 |
pd.crosstab(df["High"],[df["Size"],df["Weight"]],rownames=["High"],colnames=["Size","Weight"])
Size | 中 | 大 | 小 |
---|
Weight | 中 | 轻 | 重 | 重 | 中 | 轻 |
---|
High | | | | | | |
---|
中 | 1 | 1 | 0 | 1 | 0 | 0 |
---|
低 | 0 | 0 | 1 | 0 | 1 | 2 |
---|
高 | 0 | 1 | 0 | 2 | 1 | 0 |
另一种 宽表转长表 pd.wide_to_long()
np.random.seed(123)df = pd.DataFrame({"A1970":{0:"a",1:"b",2:"c"},"A1980":{0:"d",1:"e",2:"f"},"B1970":{0:2.5,1:1.2,2:0.7},"B1980":{0:3.2,1:1.3,2:0.1},"X":dict(zip(range(3),np.random.randn(3)))
})
df["id"] = df.index
df
| A1970 | A1980 | B1970 | B1980 | X | id |
---|
0 | a | d | 2.5 | 3.2 | -1.085631 | 0 |
---|
1 | b | e | 1.2 | 1.3 | 0.997345 | 1 |
---|
2 | c | f | 0.7 | 0.1 | 0.282978 | 2 |
把id列用作标识列
pd.wide_to_long(df,["A","B"],i="id",j="year")
| | X | A | B |
---|
id | year | | | |
---|
0 | 1970 | -1.085631 | a | 2.5 |
---|
1 | 1970 | 0.997345 | b | 1.2 |
---|
2 | 1970 | 0.282978 | c | 0.7 |
---|
0 | 1980 | -1.085631 | d | 3.2 |
---|
1 | 1980 | 0.997345 | e | 1.3 |
---|
2 | 1980 | 0.282978 | f | 0.1 |
df = pd.DataFrame({"famid":[1,1,1,2,2,2,3,3,3],"birth":[1,2,3,1,2,3,1,2,3],"ht1":[2.8,2.9,2.2,2,1.8,1.9,2.2,2.3,2.1],"ht2":[3.4,3.8,2.9,3.2,2.8,2.4,3.3,3.4,2.9]
})
df
| famid | birth | ht1 | ht2 |
---|
0 | 1 | 1 | 2.8 | 3.4 |
---|
1 | 1 | 2 | 2.9 | 3.8 |
---|
2 | 1 | 3 | 2.2 | 2.9 |
---|
3 | 2 | 1 | 2.0 | 3.2 |
---|
4 | 2 | 2 | 1.8 | 2.8 |
---|
5 | 2 | 3 | 1.9 | 2.4 |
---|
6 | 3 | 1 | 2.2 | 3.3 |
---|
7 | 3 | 2 | 2.3 | 3.4 |
---|
8 | 3 | 3 | 2.1 | 2.9 |
把 famid,birth两列作为标识列
l = pd.wide_to_long(df,stubnames="ht",i = ["famid","birth"],j="age")
l
| | | ht |
---|
famid | birth | age | |
---|
1 | 1 | 1 | 2.8 |
---|
2 | 3.4 |
---|
2 | 1 | 2.9 |
---|
2 | 3.8 |
---|
3 | 1 | 2.2 |
---|
2 | 2.9 |
---|
2 | 1 | 1 | 2.0 |
---|
2 | 3.2 |
---|
2 | 1 | 1.8 |
---|
2 | 2.8 |
---|
3 | 1 | 1.9 |
---|
2 | 2.4 |
---|
3 | 1 | 1 | 2.2 |
---|
2 | 3.3 |
---|
2 | 1 | 2.3 |
---|
2 | 3.4 |
---|
3 | 1 | 2.1 |
---|
2 | 2.9 |
pandas 文本数据
import pandas as pd
1.cat()拼接字符串
d = pd.DataFrame(["a","b","c"],columns=['A'])
d
将某列元素拼接一列特定字符串
d["A"].str.cat(["A","B","C"],sep=",")
0 a,A
1 b,B
2 c,C
Name: A, dtype: object
将某列的元素合并为一个字符串
d["A"].str.cat(sep=",")
'a,b,c'
2.split()切分字符串
import numpy as np
import pandas as pd
d = pd.DataFrame(["a_b_c","c_d_e",np.nan,"f_g_h"],columns=["A"])
d
将某列的字符串元素进行切分
d["A"].str.split("_")
0 [a, b, c]
1 [c, d, e]
2 NaN
3 [f, g, h]
Name: A, dtype: object
3.get()获取指定位置的字符串
d = pd.DataFrame(["a_b_c","c_d_e",np.nan,"f_g_h"],columns=["A"])
d
d["A"].get(3)
'f_g_h'
4.join()对每个字符都用给定的字符串拼接起来(不常用)
d = pd.DataFrame(["a_b_c","c_d_e",np.nan,"f_g_h"],columns=["A"])
d
d["A"].str.join("!")
0 a!_!b!_!c
1 c!_!d!_!e
2 NaN
3 f!_!g!_!h
Name: A, dtype: object
5.contains()是否包含表达式(很常用)
d["A"].str.contains("d")
0 False
1 True
2 NaN
3 False
Name: A, dtype: object
d.fillna("0")[d.fillna("0")["A"].str.contains("d")]
表示或的关系用"A|B",表示且用"A.B"|"B.A"
d.fillna("0")[d.fillna("0")["A"].str.contains("c|d")]
6. replace()替换
d["A"].str.replace("_",",")
0 a,b,c
1 c,d,e
2 NaN
3 f,g,h
Name: A, dtype: object
7.repeat()重复
d["A"].str.repeat(3)
0 a_b_ca_b_ca_b_c
1 c_d_ec_d_ec_d_e
2 NaN
3 f_g_hf_g_hf_g_h
Name: A, dtype: object
8. pad()左右补齐
d["A"].str.pad(10,fillchar="*")
0 *****a_b_c
1 *****c_d_e
2 NaN
3 *****f_g_h
Name: A, dtype: object
d["A"].str.pad(10,side="right",fillchar="&")
0 a_b_c&&&&&
1 c_d_e&&&&&
2 NaN
3 f_g_h&&&&&
Name: A, dtype: object
9.center()中间补齐
d["A"].str.center(10,fillchar="?")
0 ??a_b_c???
1 ??c_d_e???
2 NaN
3 ??f_g_h???
Name: A, dtype: object
10.ljust()右边补齐
d["A"].str.ljust(10,fillchar="?")
0 a_b_c?????
1 c_d_e?????
2 NaN
3 f_g_h?????
Name: A, dtype: object
11.rjsut()左边补齐
d["A"].str.rjust(10,fillchar="?")
0 ?????a_b_c
1 ?????c_d_e
2 NaN
3 ?????f_g_h
Name: A, dtype: object
12.zfill()左边补0
d["A"].str.zfill(10)
0 00000a_b_c
1 00000c_d_e
2 NaN
3 00000f_g_h
Name: A, dtype: object
13.wrap()在指定的位置加回车符号
d["A"].str.wrap(3)
0 a_b\n_c
1 c_d\n_e
2 NaN
3 f_g\n_h
Name: A, dtype: object
14.slice()按给定点的开始结束位置切割字符串
d["A"].str.slice(1,3)
0 _b
1 _d
2 NaN
3 _g
Name: A, dtype: object
15.slice_repalce()使用给定的字符串,替换指定的位置的字符
d["A"].str.slice_replace(1,3,"?")
0 a?_c
1 c?_e
2 NaN
3 f?_h
Name: A, dtype: object
d["A"].str.slice_replace(0,3,"?")
0 ?_c
1 ?_e
2 NaN
3 ?_h
Name: A, dtype: object
16.count()计算给定单词出现的次数
d["A"].str.count("b")
0 1.0
1 0.0
2 NaN
3 0.0
Name: A, dtype: float64
17.startswith()判断是否以给定的字符串开头
d["A"].str.startswith("a")
0 True
1 False
2 NaN
3 False
Name: A, dtype: object
18.endswith()判断是否以给定的字符串结束
d["A"].str.endswith("e")
0 False
1 True
2 NaN
3 False
Name: A, dtype: object
19.findall()查找所有符合正则表达式的字符,以数组形式返回
d["A"].str.findall("[a-z]")
0 [a, b, c]
1 [c, d, e]
2 NaN
3 [f, g, h]
Name: A, dtype: object
20.match()检测是否全部匹配给定的字符串或表达式
d["A"].str.match("[d-z]")
0 False
1 False
2 NaN
3 True
Name: A, dtype: object
21.extact()抽取匹配的字符串出来,注意要加上括号,把你需要抽取的东西标注上
d["A"].str.extract("([d-z])")
22.len()计算字符串的长度
d["A"].str.len()
0 5.0
1 5.0
2 NaN
3 5.0
Name: A, dtype: float64
23.strip()去除前后的空白字符
df = pd.DataFrame(["a_b ","d_e ",np.nan,"f_g "],columns=["B"])
df
df["B"].str.strip()
0 a_b
1 d_e
2 NaN
3 f_g
Name: B, dtype: object
24.rstrip()去除后面的空白字符
df["B"].str.rstrip()
0 a_b
1 d_e
2 NaN
3 f_g
Name: B, dtype: object
25.lstrip()去除前面的空白字符
df["B"].str.lstrip()
0 a_b
1 d_e
2 NaN
3 f_g
Name: B, dtype: object
26.partition()把字符串数组切割成为DataFrame,注意切割只是切割称为三部分,分隔符前,分隔符,分隔符后
d["A"].str.partition("_")
| 0 | 1 | 2 |
---|
0 | a | _ | b_c |
---|
1 | c | _ | d_e |
---|
2 | NaN | NaN | NaN |
---|
3 | f | _ | g_h |
27.rpartition()从右切起
d["A"].str.rpartition("_")
| 0 | 1 | 2 |
---|
0 | a_b | _ | c |
---|
1 | c_d | _ | e |
---|
2 | NaN | NaN | NaN |
---|
3 | f_g | _ | h |
28.lower()全部小写
d["A"].str.lower()
0 a_b_c
1 c_d_e
2 NaN
3 f_g_h
Name: A, dtype: object
29.upper()全部大写
d["A"].str.upper()
0 A_B_C
1 C_D_E
2 NaN
3 F_G_H
Name: A, dtype: object
30.find()从左边开始,查找给定字符串的所在位置
d["A"].str.find("d")
0 -1.0
1 2.0
2 NaN
3 -1.0
Name: A, dtype: float64
31.rfind()从右边开始,查找给定字符串的所在位置
d["A"].str.rfind("c")
0 4.0
1 0.0
2 NaN
3 -1.0
Name: A, dtype: float64
32.index()查找给定字符串的位置,注意,如果不存在这个字符串,那么会报错
d["A"].str.index("_")
0 1.0
1 1.0
2 NaN
3 1.0
Name: A, dtype: float64
33.rindex()从右边开始查找,给定字符串的位置
d["A"].str.rindex("_")
0 3.0
1 3.0
2 NaN
3 3.0
Name: A, dtype: float64
d["A"].str.rindex("_")
0 3.0
1 3.0
2 NaN
3 3.0
Name: A, dtype: float64
34.capitalize()首字符大写
d["A"].str.capitalize()
0 A_b_c
1 C_d_e
2 NaN
3 F_g_h
Name: A, dtype: object
35.swapcase() 大小写互换
d["A"].str.capitalize().str.swapcase()
0 a_B_C
1 c_D_E
2 NaN
3 f_G_H
Name: A, dtype: object
36.isalnum()是否全部是数字和字母组成
d["A"].str.isalnum()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
37.isalpha()是否全部是字母
d["A"].str.isalpha()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
38.isdigit()是否全部都是数字
d["A"].str.isdigit()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
39.isspace()是否为空格
d["A"].str.isspace()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
40.islower()是否全部小写
d["A"].str.islower()
0 True
1 True
2 NaN
3 True
Name: A, dtype: object
41.isupper()是否全部大写
d["A"].str.isupper()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
42.istitle()是否只有首字母为大写,其他字母为小写
d["A"].str.istitle()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
43.isnumeric()是否是数字
d["A"].str.isnumeric()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
44.isdecimal()是否全部是数字
d["A"].str.isdecimal()
0 False
1 False
2 NaN
3 False
Name: A, dtype: object
pandas 时序数据