pandas库
1.介绍
- Pandas 可以从各种文件格式比如 CSV、JSON、SQL、Microsoft Excel 导入数据。
- Pandas 可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。
- Pandas 广泛应用在学术、金融、统计学等各个数据分析领域。
导入库import pandas as pd
2.基础
-
Pandas Series 类似表格中的一个列(column),类似于一维数组,可以保存任何数据类型。
构造方法:
pandas.Series( data, index, dtype, name, copy)
参数说明:
data:一组数据(ndarray 类型)。
index:数据索引标签,如果不指定,默认从 0 开始。
dtype:数据类型,默认会自己判断。
name:设置名称。
copy:拷贝数据,默认为 False。- 示例:
# 创建一列 data=['Jarry','Tom','Ailce','Angel'] column=pd.Series(data=data,index=['one','two','three','four']) print(column) """ 运行结果: one Jarry two Tom three Ailce four Angel dtype: object """
-
DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。
构造方法:
pandas.DataFrame( data, index, columns, dtype, copy)
参数说明:
data:一组数据(ndarray、series, map, lists, dict 等类型)。
index:索引值,或者可以称为行标签。
columns:列标签,默认为 RangeIndex (0, 1, 2, …, n) 。
dtype:数据类型。
copy:拷贝数据,默认为 False。- 示例:
# 创建表格 data=[['chrome',10],['edge',11],['firefox',12]] table=pd.DataFrame(data=data,columns=['site','age']) print(table) print(table.dtypes) """ 运行结果: site age 0 chrome 10 1 edge 11 2 firefox 12 site object age int64 dtype: object """
-
series方法:
- 重复值
- s.unique():返回一个值不重复的数组
- s.nunique(dropna=True):返回不重复的个数, 默认不统计nan
- 空值
- s.isnull()-> pd.isnull(s)或 s.notnull()-> pd.notnull(s):是否存在空值
- s.dropna(axis=0, inplace=False):删除空值
- s.fillna(value=None, method=None, axis=None, inplace=False):填充空值
- s.count():统计series里非NaN数据个数
- 排序
- 按值进行排序:s.sort_values(axis=0, ascending=True, inplace=False)(参数:ascending=True, 默认升序)
- 按索引进行排序:s.sort_index(axis=0, level=None, ascending=True, inplace=False)
- 数值统计
与Numpy的统计函数一样:
Series.max()
Series.min()
Series.mean()
Series.var()
Series.std()
Series.mdiean()
Series.sum() - Series.str–字符串处理
- 字符大小写转换
Series.str.lower() 转换为小写
Series.str.upper() 转换为大写
Series.str.title() 单词首字符大写
Series.str.capitalize() 第一个字符大写
Series.str.swapcase() 大小写相互转换 - 字符串拼接:pd.Series.str.cat(seq)
a.str.cat(a, sep=',') # 拼接指定分隔符 #结果:0 aSd,aSd # 1 asd,asd # 2 dfd fsAsf sfs,dfd fsAsf sfs # dtype: object
- 在字符间插入字符:Series.str.join()
- 字符串内容判断:
- contains(): 判断指定字符串或正则表达式是否在序列或索引中
参数 说明
pat 字符串或正则表达式
case=True 是否区分大小写
flags=0 可传入re.IGNORECASE之类的参数
na=nan 缺失值填充
regex=True 是否使用正则表达式匹配 - endswith(): 判断是否以给定的字符串结尾
参数 说明
pat 字符串
na=nan 缺失值填充 - startswith(): 和endswith相反
- contains(): 判断指定字符串或正则表达式是否在序列或索引中
- 提取内容:Series.str.extract(pat, flags=0, expand=None)
extract(): 使用正则表达式提取需要的内容(只返回第一次匹配到的内容)
extractall(): 使用正则表达式提取需要的内容(返回所有匹配到的内容)
参数 说明
pat 正则表达式(必须含有捕获组, 超过一个必然返回DataFrame),若捕获组设有name则将作为返回的列标签
flags=0 可传入re.IGNORECASE之类的参数 - 字符串分割
- 更新字符串(替换)
- 字符大小写转换
- 重复值
-
DataFrame
- .ndim, .shape, .size: 查看维数,形状,元素个数。
- DataFrame.describe( include= [np.number]):include:'all’或者[np.number 或 np.object]。numberic只对元素属性为数值的列做数值统计,object只对元素属性为object的列做类字符串统计。
-
数据清洗方法
- 一致性检查:一致性检查是根据每个变量的合理取值范围和相互关系,检查数据是否合乎要求,发现超出正常范围、逻辑上不合理或者相互矛盾的数据。
- 缺失值处理
- 检查某列是否存在缺失值
df.B.isnull()
;统计缺失值df.isnull().sum()
- 删除数据
DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
- 数据填充
DataFrame.fillna(value=None, method=None, axis=None, inplace=False)
- 人工填写
- 全局常量填充
- 统计量填充:缺失值为连续数值型,使用平均值或中位数来填充(中位数更具鲁棒性)
df.fillna(df.mean()) # 均值填充
。缺失值为离散数值型,使用众数填充。 - 热卡填充:对于一个包含空值的对象,在完整数据集中找一个与他最相似的对象,用这个对象的值来进行填充。
- 回归:首先选择若干个预测缺失值的自变量,然后建立回归方程估计缺失值。
- 建模填充:可以将缺失值作为新的label,部分其他属性值作为特征,建立模型得到预测值并进行填充。如RF,LGB
- 多重填充:
- 检查某列是否存在缺失值
- 重复值处理:
df.drop_duplicates(subset=None, keep='first', inplace=False)
去除特定列下面的重复行。 - 异常值处理
- 异常点检测
- 异常点处理
- 删除异常值
- 不处理
- 统计量替换
- 视为缺失值
- 数据类型转换: astype()函数可用于转化dateframe某一列的数据类
-
函数处理
- map(function, iterable, …)
- 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
- 示例:
list(map(square, [1,2,3,4,5]))
返回[1,4,9,16,25]
- lambda表达式(一行函数,匿名函数)
- lambda 参数:操作(参数)
- 示例:
myadd = lambda x, y: x + y myadd(3, 5) # 结果:8 # 使用 lambda 匿名函数 m = map(lambda x: x ** 2, [1, 2, 3, 4, 5]) list[m] # 结果 [1, 4, 9, 16, 25]
- apply()函数
DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)
func : 该函数最有用的是第一个参数,这个参数是函数,相当于C/C++的函数指针。这个函数需要自己实现.
axis: axis = 1,就会把一行数据作为Series的数据
返回值:将所有结果组合成一个Series数据结构并返回。- 示例:
df1 = pd.DataFrame({ 'sex':list('FFMFMMF'), 'smoker':list('YNYYNYY'), 'age':[21,30,17,37,40,18,26], 'weight':[120,100,132,140,94,89,123]}) # 定义区分成年人与未成年人函数 def bin_age(age): if age >=18: return 1 else: return 0 df1['adult'] = df1['age'].apply(bin_age) # apply返回一个series,然后赋值给一个列 df1['adult'] = df1['age'].apply(lambda x : 1 if x >18 else 0) # lambda表达式 # 取出抽烟和不抽烟的体重前二 def top(df, col, n=5): return df.sort_values(by=col)[-n:] # top函数返回的DataFrame对象,将其所有返回的结果(在这是返回俩次)用concat连接,形成最终结果 test = df1.groupby('smoker').apply(top, col='weight', n=2)
- map()方法和apply()方法的区别
- map() 是一个Series的函数,DataFrame结构中没有map()。
- map()将一个自定义函数应用于Series结构中的每个元素(elements)。
- DataFrame中有apply() 和 applymap(),但没有map().
- map()是python 自带的方法, 可以对df某列内的元素进行操作
toward_dict = {'1': '东', '2': '南', '3': '西', '4': '北'} def towardfunc(snum): if snum == '': return np.nan else: return toward_dict[snum] df['toward'].map(towardfunc) df['toward'].apply(towardfunc) # 去除货币列中的","和"$",并转换数据类型为"float64" df["2016"].apply(lambda x: x.replace(",","").replace("$","")).astype("float64") # 去除百分号 df["Percent Growth"].apply(lambda x: x.replace("%","")).astype("float")/100
- astype()函数
- 示例
df["2016"] = df["2016"].apply(lambda x: x.replace(",","").replace("$","")).astype("float64") df["2017"] = df["2017"].apply(lambda x: x.replace(",","").replace("$","")).astype("float64") df["Percent Growth"] = df["Percent Growth"].apply(lambda x: x.replace("%","")).astype("float")/100
- 示例
- 其他
df["Start_date"] = pd.to_datetime(df[['Month', 'Day', 'Year']])
- map(function, iterable, …)
-
分组聚合
- groupby():分组
示例:
在groupby之后的一系列操作(如agg、apply等),均是基于子DataFrame的操作.# 采用模拟生成的10个样本数据 company=["A","B","C"] data = pd.DataFrame({ "company":[company[x] for x in np.random.randint(0,len(company),10)], "salary":np.random.randint(5,50,10), "age":np.random.randint(15,50,10) }) group = data.groupby("company") list(group) # 转换成列表的形式后,可以看到,列表由三个元组组成, # 每个元组中,第一个元素是组别(这里是按照company进行分组,所以最后分为了A,B,C),第二个元素的是对应组别下的DataFrame # 其他形式 list(data.groupby(by="company")) list(data.groupby(data['company'])) # 分组信息 group.groups # 查看每个分组的组内数量 group.size() # 循环迭代 for gp, dat in group: print("组别:", gp) print("数据:\n", dat)
- agg 聚合操作
分组结果的内置统计函数:
df.groupby(‘key’).sum()
df.groupby(‘key’).max()
df.groupby(‘key’).min()
df.groupby(‘key’).mean()
df.groupby(‘key’).size()
df.groupby(‘key’).count()
df.groupby(‘key’).describe()# 求不同公司员工的平均年龄和平均薪水 data.groupby("company").mean() group.agg('mean') data.groupby("company").agg('mean') # 获取某一列值 data.groupby('company').mean()['salary'] data.groupby('company')['salary'].mean() # 改变列索引 data.groupby('company',as_index=False).agg('mean')
- 其他
# 使用自定义的函数找出每个工资中年龄最大的员工 def get_oldest_staff(x): df = x.sort_values(by = 'age',ascending=True) # 取一列 return df.iloc[-1,:] data.groupby('company',as_index=False).apply(get_oldest_staff) # 两者的区别在于,对于groupby后的apply,以分组后的子DataFrame作为参数传入指定函数的,基本操作单位是DataFrame,而之前介绍的apply的基本操作单位是Series。还是以一个案例来介绍groupby后的apply用法。
- groupby():分组
-
数据合并
- pandas中的concat函数可以将数据根据不同的轴作简单的融合。concat函数本质上是在所有索引上同时进行对齐合并,而如果想在任意列上对齐合并,则需要merge函数,其在sql应用很多。pandas中的merge()函数类似于SQL中join的用法,可以将不同数据集依照某些字段(属性)进行合并操作,得到一个新的数据集。
- merge():列合并
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort = False)
- concat():轴向连接
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False)
-
padas可视化
-
Pandas 的数据可视化的实现底层依赖于 matplotlib
-
DataFrame.plot( )函数
- 折线图
- 示例
# 随机生成数据 df = pd.DataFrame(np.random.randint(-10, 10, (10, 4)), index=pd.date_range("1/1/2020", periods=10), columns=list("ABCD")) # 调用 plot 方法就可以看到画图的结果了。默认情况下参数 kind="line" 表示图的类型为折线图。通过折线图可以看出数据随着某个变量的变化趋势。 df.plot() # 运行结果:默认情况下,plot 会将索引作为 x 轴,列作为 y 轴,然后画出 line 图。
2. plot()的kind关键字参数 line为折线图 bar纵向或barh横向 为条形 hist为直方图 boxplot为盒型图 area为“面积” scatter为散点图
-
柱状图
df.plot(kind="bar")
df.plot(kind="bar", x="A", y=["B", "C"])
:指定x,y轴df.plot(kind="bar", y=["B", "C"], stacked=True)
:条形堆积图
-
直方图
示例:df2 = pd.DataFrame({'a':np.random.randn(1000)+1, 'b':np.random.randn(1000), 'c':np.random.randn(1000) - 1}, columns=['a', 'b', 'c']) df2.plot(kind="hist", bins=20) df2.hist(bins=20) # (3个小图)
-
其他
- 散点图
ax = df.plot(kind="scatter", x="A", y="B", color="blue") df.plot(kind="scatter", x="C", y="B", color="green", ax=ax) # 绘制在一张图中
- 饼图
a = df.A[:5] a.abs().plot.pie(subplots=True, figsize=(4, 4), autopct="%.2f")
- 六边形容器图
df = pd.DataFrame(np.random.randn(1000, 2), columns=["A", "B"]) df["B"] = df["B"] + np.arange(1000) df.plot(kind="hexbin", x="A", y="B", gridsize=10)
- 折线图
-
正则表达式
- 正则表达式是用来匹配字符串或者子串的一种模式,匹配的字符串可以很具体,也可以很一般化。
- 正则表达式规则
子表达式 匹配内容 . 匹配除了换行符之外的内容 \w 匹配所有字母和数字字符 \d 匹配所有数字,相当于 [0-9] \s 匹配空白,相当于 [\t\n\t\f\v] \W,\D,\S 匹配对应小写字母形式的补 […] 表示可以匹配的集合,支持范围表示如 a-z, 0-9 等 (…) 表示作为一个整体进行匹配 | 表示逻辑或 ^ 表示匹配后面的子表达式的补 * 表示匹配前面的子表达式 0 次或更多次 + 表示匹配前面的子表达式 1 次或更多次 ? 表示匹配前面的子表达式 0 次或 1 次 {m} 表示匹配前面的子表达式 m 次 {m,} 表示匹配前面的子表达式至少 m 次 {m,n} 表示匹配前面的子表达式至少 m 次,至多 n 次 - re.match(pattern, string[, flags]) & re.search(pattern, string[, flags])
两者都寻找第一个匹配成功的部分,成功则返回一个 match 对象,不成功则返回 None,不同之处在于 re.match 只匹配字符串的开头部分,而 re.search 匹配的则是整个字符串中的子串。 - re.findall(pattern, string) 返回所有匹配的对象,re.finditer 则返回一个迭代器。
- 通常,match.group(0) 匹配整个返回的内容,之后的 1,2,3,… 返回规则中每个括号(按照括号的位置排序)匹配的部分。
少 m 次,至多 n 次 | - re.match(pattern, string[, flags]) & re.search(pattern, string[, flags])
两者都寻找第一个匹配成功的部分,成功则返回一个 match 对象,不成功则返回 None,不同之处在于 re.match 只匹配字符串的开头部分,而 re.search 匹配的则是整个字符串中的子串。 - re.findall(pattern, string) 返回所有匹配的对象,re.finditer 则返回一个迭代器。
- 通常,match.group(0) 匹配整个返回的内容,之后的 1,2,3,… 返回规则中每个括号(按照括号的位置排序)匹配的部分。