赞
踩
pandas 是基于 numpy 的一种工具,该工具是为了解决数据分析任务而创建的。
它有两种常见的数据类型:Series,DataFrame。Series 是 pandas 中最基本的对象,类似一维数组,可以自定义标签(也就是索引),通过索引可以访问数组中的数据。DataFrame 是一个二维表结构,能够存储多种不同类型的数据,并且每一个坐标轴都有自己的标签,可以把它当作一个 Series 的字典项。
pandas 功能强大,这里只列举常见的一些功能,没有涉及到的功能可以去 [官方文档] 查看。
# 通过列表创建,此时会默认从 0 开始创建索引
sel1 = Series([1,2,3,4])
print(sel1)
# 通过指定数据和索引创建
sel2 = Series(data=[1,2,3,4], index=list('abcd'))
print(sel2)
# 通过字典创建,字典的键是索引,值是数据
d3 = {'red':120, 'blue':30, 'green':80}
sel3 = Series(d3)
print(sel3)
Series 的索引值可以重新设置:
sel1.index = list('bdca')
这种方式会直接改变 Series 本身的索引,如果不想改变原始 Series,可以使用 reindex:
sel4 = sel1.reindex(list('abcdr'))
这种方式返回一个新的 Series,缺失值用 NaN 填补。
对 Series 的算术运算都是基于 index 进行的,Pandas 会根据 index 获取相关数据进行加减乘除,运算结果会以浮点数的形式存储,避免精度丢失!如果在 Series 中找不到相应的 index,则会返回 NaN!
sel1 = Series(data=[1,2,3,4], index=list('abcd'))
sel2 = Series(data=[9,8,7,6], index=list('bcdk'))
sel1+sel2 # 找不到的 index 返回NaN
sel1[sel1>2] # Series 过滤,sel1>2 用元素值判断,返回真值数组
sel1*2 # 标量乘法
np.square(sel1) # 直接加到 numpy 中做运算
DataFrame 的三个重要属性:data,index,columns!
# 通过二维数组创建
df1 = DataFrame(np.random.randint(0,10,(4,4)), index=[1,2,3,4], columns=list('abcd'))
# 通过字典创建,字典的键是列索引,行索引需另行指定
d2 = {'language':['python', 'C++', 'java', 'PHP'],
'rank':[1,2,3,4],
'score':[90, 60, 100, 65]}
df2 = DataFrame(d2) # index可以省略(有默认值)
# 字典的值也可以是 Series 对象,相同的索引会一一对应,缺少的值会用NaN填充
d3 = {'a':sel1, 'b':sel2, 'c':sel3}
df3 = DataFrame(d3)
DataFrame 也可以转换成字典:
df3.to_dict(orient='dict') # orient 可以选择不同的字典返回模式
DataFrame 中两个获取数据最常用的属性:loc,iloc。loc 通过标签索引获取行数据,iloc 通过位置获取行数据:
df3.loc['a'] # 根据行索引获取一行
df3.loc['a', 'b'] # 根据行索引、列索引获取具体位置数据
df3.loc['a', ['b','c']] # 获取一行多列
df3.loc[['a','b'], ['a', 'b']] # 获取多行多列
df3.iloc[1] # 根据位置获取一行
df3.iloc[1, 2] # 根据位置获取某行某列
df3.iloc[1, 2:4] # 根据位置获取一行多列
df3.iloc[1:3, 2:4] # 根据位置获取多行多列
DataFrame 中修改某行某列元素的值:
df3.iloc[2, 3] = 'pandas' # 修改 (2,3)位置的值
df3.iloc[2] = [1,2,3,4,5] # 修改第2行的值
df3.iloc[:, 2] = [1,2,3,4] # 修改第2列的值
DataFrame 中的排序:
# 根据某一列的元素值升序排序
df4 = df3.sort_values(by='b', ascending=True)
# 根据行索引排序
df4 = df3.sort_index()
# 直接修改行索引,所有的行索引都修改
df4.index = list('abcdefgh')
# 单独修改某一行、某一列的索引,用到字典;inplace 为 True 表示在元 df 上修改
df4 = df3.rename(index={'a':'aa'}, columns={'a':'bb'}, inplace=False)
# rename 还可以传入函数,输入是原来的索引,返回值作为修改后的索引
df4 = df3.rename(index=test_map, columns=test_map)
# 将某一列的内容作为行索引,drop=False 保留该列
df4 = df3.set_index('a', drop=False)
# 将某一行的内容作为列索引,axis=1 就表示转化为列索引
df4 = df3.set_axis(df3.iloc[0], axis=1, inplace=False)
在框的最后加上一列:
# 要求列名不能同之前的重复,列的元素数量必须同之前的吻合
df4['bbc'] = [1,2,3,4,5,4,5,9]
在指定位置插入一列:
# iloc:插入位置,columns:列名,value:该列元素值
df4.insert(iloc=2, columns='python', value=[9,8,7,76,6,6,4,3])
在框的最后插入一行:
df4.loc['bbc'] = [1,2,3,4,5]
panda 可操作的文件类型有很多,例如 .csv
、JSON
、HTML
、Excel
、HDF5
等等,这里只展示基本的几种。
CSV(Comma-Separated Values,逗号分隔值,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。
读取 .csv
,[接口文档]:它的输入可以是文件路径、字符串数据、网页链接等
import pandas as pd from io import StringIO data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" # csv 文件其实就是以逗号分隔的一行一行的文本 pd.read_csv(StringIO(data)) """ output: col1 col2 col3 0 a b 1 1 a b 2 2 c d 3 """ pd.read_csv(StringIO(data), usecols=lambda x: x.upper() in ["COL1", "COL3"]) # 读取指定的列 """ output: col1 col3 0 a 1 1 a 2 2 c 3 """ pd.read_csv(StringIO(data), skiprows=lambda x: x % 2 != 0) # 跳过部分行 """ output: col1 col2 col3 0 a b 2 """
保存 .csv
,[接口文档]:
df.to_csv("mi.csv", index=False, header=False) # 保存 .csv 文件时不保存索引和表头
df.to_csv("mi.csv", encoding='utf_8_sig') # 一般表内数据有中文时,需要指定编码格式,否则会全是乱码
.xlsx
的操作方式跟 .csv
基本一致,读取文件 [接口文档],保存文件 [接口文档]。
pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, ...)
df.to_excel(excel_writer, sheet_name='Sheet1', na_rep='', ...)
假设有一组内嵌的 JSON 数据文件 nested_list.json
:
{ "school_name": "ABC primary school", "class": "Year 1", "students": [ { "id": "A001", "name": "Tom", "math": 60, "physics": 66, "chemistry": 61 }, { "id": "A002", "name": "James", "math": 89, "physics": 76, "chemistry": 51 }, { "id": "A003", "name": "Jenny", "math": 79, "physics": 90, "chemistry": 78 }] }
直接使用 read_json
读取会有一些问题:
df = pd.read_json('nested_list.json')
"""
output:
school_name class students
0 ABC primary school Year 1 {'id': 'A001', 'name': 'Tom', 'math': 60, 'phy...
1 ABC primary school Year 1 {'id': 'A002', 'name': 'James', 'math': 89, 'p...
2 ABC primary school Year 1 {'id': 'A003', 'name': 'Jenny', 'math': 79, 'p...
"""
上面的 id/name/math...
等内容没有解析出来,被当做一项了。更好的做法是 json_normalize
:
# 使用 Python JSON 模块载入数据
with open('nested_list.json','r') as f:
data = json.loads(f.read())
# 展平数据
df_nested_list = pd.json_normalize(data, record_path =['students']) # 指定输出 student 项目下的内容
print(df_nested_list)
"""
output:
id name math physics chemistry
0 A001 Tom 60 66 61
1 A002 James 89 76 51
2 A003 Jenny 79 90 78
"""
df.to_json()
是可以将 DataFrame
保存为文件,也可以转换成 JSON
字符串(如果不指定输出文件路径时):
json = dfj.to_json()
print(json)
"""
output:
'{"A":{"0":-1.2945235903,"1":0.2766617129,"2":-0.0139597524,"3":-0.0061535699,"4":0.8957173022},"B":{"0":0.4137381054,"1":-0.472034511,"2":-0.3625429925,"3":-0.923060654,"4":0.8052440254}}'
"""
转换时可以指定按哪个方向转,具体方式可查看官方文档。
缺失值统计:
df.isnull() # 判断哪些位置是缺失值,返回跟 df 形状一样的表格,表格内为 True 的地方表示缺失
df.isnull().sum() # 统计有多少缺失值
过滤缺失值:
df = df.dropna() # 所有包含 NaN 的行都将被丢弃,也就是 how='any'
df = df.dropna(how='all') # 过滤掉整行全部是 NaN 的行
df = df.dropna(axis=1, how='all') # 按列进行过滤
df = df1.dropna(thresh=2) # 过滤掉非NaN数据个数少于2的行
填充缺失值:
df = df.fillna(10) # 用常数填充
df = df.fillna({0:10, 1:20, 2:30}) # 通过字典填充,字典的键代表着列
df = df.fillna(df.mean()) # 用平均值填充
df = df.iloc[:, 1].fillna(5) # 单独填充某一列
df = df.fillna(method='ffill') # 用单元格上方(前面的)的数据来填充
df = df.fillna(method='bfill') # 用单元格下方(后面的)的数据来填充
df = df.fillna(5, limit=1) # 限制填充哪一行
判断每一行是否重复,它会跟之前的所有行作比较:
df.duplicated() # 返回的是 bool 值
过滤重复行:
df = df.drop_duplicates() # 过滤掉所有重复行
df = df.drop_duplicates(['A']) # 指定列过滤重复行
df = df.drop_duplicates(['A'], keep='last') # 保留重复行中的最后一行
df.replace(to_replace='\n', value=' ', regex=True) # 替换表中所有换行符为空格
df.replace(to_replace=[r"\\t|\\n|\\r", "\t|\n|\r"], value=["",""], regex=True, inplace=True) # 一次替换多个字符
df['result'].map(lambda x: x.split('邮箱')[0]) # result 列的所有元素,以"邮箱"为分隔符,提取分隔后的第一个值,删除后面的
Pandas 提供了 concat
,merge
,join
和 append
四种方法用于 dataframe
的拼接。
可用于多个 df
之间的行方向或列方向的拼接,默认是行拼接、取并集。更多示例参考官方文档。
pd.concat(
objs,
axis=0,
join='outer',
ignore_index=False,
keys=None,
levels=None,
names=None,
verify_integrity=False,
copy=True
)
result = pd.concat([df1, df4], axis=1, sort=False)
df1 = pd.DataFrame({'red':[1,3,5], 'green':[9,0,6]}, index=list('abc'))
df2 = pd.DataFrame({'blue':[1,9,8], 'yellow':[6,6,7]}, index=list('cde'))
df1.join(df2, how='left') # 左连接,以 df1 的行索引为基准,找不到列的填充 NaN
df1.join(df2, how='right') # 右连接
df1.join(df2, how='outer') # 外连接,合并 df1/df2 的所有行,找不到的填充 NaN
df1.join([df2, df3]) # 合并多个 DataFrame 对象
result = left.join(right)
主要是用于两个 df
之间的行方向或列方向的拼接,默认是列拼接、取交集。更多示例参考官方文档。
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,
validate=None
)
result = pd.merge(left, right, on='key')
result = pd.merge(left, right, on=['key1', 'key2'])
left
被选中的第 2 条数据,分别要与 right
的第 1/2 条数据做拼接,因为他们的 key1/key2
相同。
result = df1.append(df2)
六、多层索引
七、时间序列
八、分组聚合
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。