pandas的21个基本操作
By 青衣极客 Blue Geek In 2019-09-11
常做数据分析的朋友大概没有人不知道这款大名鼎鼎的python第三方库——pandas。绝大多数的朋友们或许会见到一些开源代码中使用pandas,也可能自己处理表格数据时偶尔用到,但是对于pandas的一些基础用法却并没有系统性的总结。前段时间阅读了一份英文版的pandas使用总结,总感觉有些地方描述得不太清楚,可操作性也不太强。这里就重新写了一份中文版的,但愿喜欢使用这款工具的朋友能够从中有所收获。
与其他的python模块使用一样,首先需要导入pandas模块。
import os
import pandas as pd
import numpy as np
1. 怎样读取csv文件或者文本文件?
通常我们都需要从文件中读取一些数据,而pandas也为这种需求提供了简便的接口read_csv()函数。首先我们来看一个从csv文件读取数据的例子。
''' data.csv
A,B,C,D
1,2,3,4
5,6,7,8
'''
csv_path = '../../data/data.csv'
df = pd.read_csv(csv_path, sep=',', header=0, index_col=False, names=None)
print(df)
A B C D
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
接下来再来看一个从文本文件读取数据的例子
''' data.txt
A B C D
1 2 3 4
5 6 7 8
'''
txt_path = '../../data/data.txt'
df = pd.read_csv(txt_path, sep=' ', header=0, index_col=False, names=None)
print(df)
A B C D
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
以上演示的两种从文件载入数据的方式基本能够满足绝大多数的数据载入需求,如果还希望从别的文件中载入数据,比如excel文件xls等,pandas都已经提供了对应的API。
2. 怎样使用已有数据创建data frame?
如果不从文件载入数据,能否直接使用python代码创建DataFrame呢?这种合理需求当然是应该满足的。这里也演示两种创建DataFrame的方式,首先来看一个从dict类型数据创建DataFrame的例子。
# 从词典数据创建data frame
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
print(df)
A B C D
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
再来看一个从numpy数组创建DataFrame的例子。
# 从numpy数组创建data frame
np_data = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
col_names = ['A', 'B', 'C', 'D']
df = pd.DataFrame(data=np_data, columns=col_names)
print(df)
A B C D
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
这两种方式用起来都不难,只是适用场景稍有差别。如果需要在list数据的基础上创建DataFrame那么词典方法更简单,如果已经获得到了numpy数据的数据,那么第二种方式更省事。
3. 怎样可视化data frame的顶部和底部数值?
查看pandas基础结构DataFrame的部分数据内容,以了解数据的基本情况,这是分析新数据时常常需要做的事情。在pandas中,可以使用head()函数查看前若干行数据,示例如下:
d_dict = {'A':[1,2,3,4,5,6,7,8,9,10,11,12]}
df = pd.DataFrame(data=d_dict)
df.head(5)
| A | |
|---|---|
| 0 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
如果需要查看表格尾部的若干行数据,tail()函数可以派上用场,示例如下:
df.tail(3)
| A | |
|---|---|
| 9 | 10 |
| 10 | 11 |
| 11 | 12 |
4. 怎样重命名若干列?
有时可能需要对表格中若干列的表头名字进行重命名,而保持其他列的表头名不变。rename()函数或许是个不错的选择。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
new_df = df.rename(columns={'A':'new_A', 'B':'new_B', 'C':'new_C'})
print(new_df)
new_A new_B new_C D
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
5. 怎样获取列的名字形成一个列表?
如何抽取表格中所有列的名字?这是分析数据特征项物理含义的几个基本操作。pandas为DataFrame提供了column.tolist()函数实现这种需求。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
name_list = df.columns.tolist()
print(name_list)
['A', 'B', 'C', 'D']
6. 怎样获取一列数据的值出现频率?
对某项特征中数据出现的频率进行分析往往是了解数据组成的一种方法,特别对于类型特征的数据。pandas为列数据对象提供了value_counts()函数完成这种操作。
d_dict = {'A':[1,5,1], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
A_cnt = df['A'].value_counts()
print(A_cnt)
print(type(A_cnt))
1 2
5 1
Name: A, dtype: int64
<class 'pandas.core.series.Series'>
7. 怎样删除行以及重置索引
由于数据不符合要求,需要删除表格中的某些行,drop()函数可以达到目的。但是该操作完成之后,行的索引就不连续了,这时可能会需要使用reset_index()函数重置一次行索引。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
df = df.drop([1]) # 删除index为1的行
print(df)
new_df = df.reset_index(drop=True, inplace=False) # 重置索引
print(new_df)
A B C D
0 1 2 3 4
2 9 10 11 12
A B C D
0 1 2 3 4
1 9 10 11 12
8. 怎样移除一列?
如果不再需要某个特征的数据,那么可以使用drop()函数指定列名来删除对应的列数据。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
df.drop(columns=['B'], inplace=True) #删除'B'列,原处修改
print(df)
A C D
0 1 3 4
1 5 7 8
2 9 11 12
9. 怎样在data frame中改变索引?
除了重置行索引,能不能直接设置行索引呢?这个也是可以的,直接使用set_index()函数完成即可。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
print('before:\r\n', df)
df.set_index(['B'], inplace=True)
print('after:\r\n', df)
before:
A B C D
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
after:
A C D
B
2 1 3 4
6 5 7 8
10 9 11 12
10. 怎样移除包含nan值的行或者列?
有时采集的数据中不可避免地存在nan这种无效数据,那么就需要对包含nan的数据点(即样本)进行移除。
d_dict = {'A':[1,np.nan,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
print('before:\r\n', df)
df.dropna(axis=1, inplace=True)
print('after:\r\n', df)
before:
A B C D
0 1.0 2 3 4
1 NaN 6 7 8
2 9.0 10 11 12
after:
B C D
0 2 3 4
1 6 7 8
2 10 11 12
11. 怎样根据指定条件对data frame进行切片?
DataFrame也是一个二维的数据,在通常的使用中,对其进行切片操作就少不了了。以下就演示单个条件和多个条件的切片例子。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
# 单个条件
mask = df['A'] > 4
slide_df = df[mask]
print('single condition:\r\n', slide_df)
# 多个条件
mask = (df['A'] > 4) & (df['B'] > 7)
print('multiple condition:\r\n', df[mask])
single condition:
A B C D
1 5 6 7 8
2 9 10 11 12
multiple condition:
A B C D
2 9 10 11 12
12. 怎样根据给定的索引或者列名进行切片?
如果只是想要获取某些指定的列名或者行索引的数据切片,pandas提供的一组函数将会非常有用。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
print(df.iat[1,2]) # 根据整数索引进行切片
print(df.at[1, 'C']) # 根据列名进行切片
print(df.loc[[0,2], ['A', 'D']]) # 根据列名就行切片
print(df.iloc[[0,2], [0,3]]) # 根据整数索引进行切片
7
7
A D
0 1 4
2 9 12
A D
0 1 4
2 9 12
13. 怎样逐行迭代?
数据表中每一列表示一个特征项,每一行表示一个数据样本,对行进行迭代以利用每个样本来进行分析是一项必不可少的操作。以下演示基于iterrows()的迭代和df.itertuples()的元组迭代。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
# 逐行迭代
sum = 0
for i, row in df.iterrows():
sum += row['A']
print(sum)
# 元组迭代器
sum = 0
for row in df.itertuples():
sum += row.A
print(sum)
15
15
14. 怎样根据列进行排序?
按照某一列对所有的行进行排序,有利于分析单个特征的具体情况。pandas提供了sort_values()函数应对这种情况。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
df.sort_values(by=['A'], ascending=False, inplace=True)
print(df)
A B C D
2 9 10 11 12
1 5 6 7 8
0 1 2 3 4
15. 怎样将一个函数应用到一系列元素?
对某个特征项的数据进行同一种操作,比如归一化,那么apply()函数会有不错的效果。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
def func_square(x):
return x*x
new = df['A'].apply(func_square)
print(new)
def func_mul(x, **kwargs):
return x*kwargs['a']
new = df['A'].apply(func_mul, a=3)
print(new)
0 1
1 25
2 81
Name: A, dtype: int64
0 3
1 15
2 27
Name: A, dtype: int64
16. 怎样对所有元素应用函数?
如果对表格中的所有数据都进行同一种操作,可以使用applymap()函数来完成这种需求。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
def func(x):
return x ** 2
new = df.applymap(func)
print(new)
A B C D
0 1 4 9 16
1 25 36 49 64
2 81 100 121 144
17. 怎样对指定list中的列元素进行切片?
对某特征项的数据满足某种条件的样本点进行筛选是数据清洗的一个重要操作。pandas提供isin()函数,判断数据是否在指定的序列中。该操作可以为切片提供条件。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
value_list = list(range(9))
print(df[df['D'].isin(value_list)])
print(df[~df['D'].isin(value_list)])
A B C D
0 1 2 3 4
1 5 6 7 8
A B C D
2 9 10 11 12
18. 怎样融合列并应用函数?
按照某一列特征项数据对其他特征数据进行统计分析,比如统计某种类别的数据的均值,如下例子就是演示这种需求的实现方式。
d_dict = {'A':[1,5,1], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
new = df.groupby(['A']).agg({'B':'mean'})
print(new)
print(df.groupby(['A']).agg(list))
B
A
1 6
5 6
B C D
A
1 [2, 10] [3, 11] [4, 12]
5 [6] [7] [8]
19. 怎样将一列元素为list的列拆为多行?
如果数据表格中的数据元素为一个序列,那么可能需要将这个序列拆分成多行。explode()函数可以用于实现该需求。
d_dict = {'A':[1,5,1], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df = pd.DataFrame(data=d_dict)
new = df.groupby(['A']).agg(list)
print(new)
print(new['B'].explode())
B C D
A
1 [2, 10] [3, 11] [4, 12]
5 [6] [7] [8]
A
1 2
1 10
5 6
Name: B, dtype: object
20. 怎样拼接两个data frame?
直接将两个数据表格在指定维度上拼接起来,常常用于增加新的样本点或者新的特征项。
d_dict = {'A':[1,5,1], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df1 = pd.DataFrame(data=d_dict)
d_dict = {'A':[1,5,1], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df2 = pd.DataFrame(data=d_dict)
print(pd.concat([df1, df2], axis=0))
print(pd.concat([df1, df2], axis=1))
A B C D
0 1 2 3 4
1 5 6 7 8
2 1 10 11 12
0 1 2 3 4
1 5 6 7 8
2 1 10 11 12
A B C D A B C D
0 1 2 3 4 1 2 3 4
1 5 6 7 8 5 6 7 8
2 1 10 11 12 1 10 11 12
21. 怎样合并两个data frame?
按照共同的一列元素来对多个数据表进行拼接,比如将学生的身份信息与考试成绩信息进行拼接。下面的例子演示了一个简单的拼接需求。
d_dict = {'A':[1,5,9], 'B':[2,6,10], 'C':[3,7,11], 'D':[4,8,12]}
df1 = pd.DataFrame(data=d_dict)
d_dict = {'A':[1,5,9], 'e':[2,6,10], 'f':[3,7,11], 'g':[4,8,12]}
df2 = pd.DataFrame(data=d_dict)
new = df1.merge(df2, on=['A'], how='inner')
print(new)
A B C D e f g
0 1 2 3 4 2 3 4
1 5 6 7 8 6 7 8
2 9 10 11 12 10 11 12
以上就是本文讨论的“pandas的21个基本操作”的具体情况。单个操作或许并没有什么神奇的地方,但是这些基本操作组合出的复杂操作足够完成很多数据分析的任务。
CHANGELOG
- 2020-04-07 增加文本说明

COMMENT
博客评论区功能由Github Issue提供,提交Issue时请以本文标题为话题。
"BG01-pandas的21个基本操作"