pandas数据分析和plot画布的使用
在我们实际生活中充满着大量的数据,那么这些数据需要怎么去筛选呢?python中的pandas给了我们非常强大的批量管理功能,同时plot画布也可以便于我们将数据可视化。
pandas
pandas中包括Series和DataFrame
pandas
是 Python 中一个非常流行的数据分析库,它提供了高效、灵活的数据结构和工具,尤其是 DataFrame
和 Series
两种数据结构,广泛用于数据清洗、处理、分析和建模。
pandas :是一个 Python 的库(包),它的名字源自“panel data”的缩写。pandas
提供了高效的数据结构和数据操作工具,特别是处理表格数据(类似数据库表或 Excel 表格)和时间序列数据。它能够让用户轻松地加载、清理、处理、变换、分析和可视化数据。
Series:是 pandas
中的一种数据结构,类似于一维数组(numpy.ndarray
),但它具备更多功能。每个 Series
由一组数据和一个与之相关的索引组成,因此它不仅仅是一个简单的列表,还可以通过标签来访问元素。Series
是 pandas
中最基础的数据类型。
- 一维数据结构。
- 包含数据(可以是任何类型,如数字、字符串、日期等)和索引。
- 索引为数据提供了标签,可以通过标签进行定位和访问。
示例:
1 2 3 4
| s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(s)
|
输出:
1 2 3 4
| b 20 c 30 d 40 dtype: int64
|
在这个例子中,s
是一个 Series
,它包含四个数据点和相应的索引标签。
Series
的内部结构:
- 数据:
[10, 20, 30, 40]
- 索引:
['a', 'b', 'c', 'd']
DataFrame:是 pandas
中最强大和常用的数据结构,它是一个二维的表格结构,类似于数据库中的表、Excel 表格或 SQL 查询的结果集。DataFrame
可以被看作是多个 Series
的组合,每个 Series
对应一个列,因此每个列都可以有自己的数据类型。
特点:
- 二维数据结构(表格形式)。
- 每列是一个
Series
,每行也有索引。
- 行和列都有标签,可以通过行标签和列标签进行数据访问。
示例:
1 2 3 4 5 6 7 8 9 10 11 12
| import pandas as pd
data = { 'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9] }
df = pd.DataFrame(data)
print(df)
|
输出:
1 2 3 4
| A B C 0 1 4 7 1 2 5 8 2 3 6 9
|
在这个例子中,df
是一个 DataFrame
,它包含三列:A
、B
和 C
,每列的数据是一个 Series
。
pandas
、Series
和 DataFrame
之间的关系
pandas
是一个库,提供了操作和分析数据的功能。
pandas
包含了 Series
和 DataFrame
这两种核心的数据结构。
Series
是 pandas
中的一维数据结构,它可以看作是 DataFrame
的一列。
Series
适用于一维数据的存储和操作,它有一个一维的数组结构和一个与之相关的索引(标签)。
DataFrame
是 pandas
中的二维数据结构,由多个 Series
组成。
- 每个
DataFrame
由多个列(Series
)组成,行和列都可以有标签(索引和列名)。
数据结构的层级关系:
pandas
是整个库。
Series
是 pandas
提供的基本数据结构之一,表示一维数据。
DataFrame
是 pandas
中的二维数据结构,由多个 Series
组成。
以上我们搞清楚了pandas、Series、DataFrame之间的关系,接下来我们看看如何使用他们。
读取
将csv文件读取成dataframe对象:
1 2
| import pandas as pd df_citygdp = pd.read_csv('city.csv', index_col=0, header=0)
|
index_col=0表示将第一列作为行索引,header=0表示将第一行作为列索引。
同样的,如果是excel文件:
1 2
| import pandas as pd df_zpcjd = pd.read_excel('综评成绩单.xlsx', index_col=[1, 2])
|
index_col=[0,1]表示将第二和第三列作为行索引。
注意:
- csv文件:是纯文本文件,每一行代表一条记录,记录中的字段由逗号或其他分隔符(如制表符、分号等)分隔。
- xlsx文件:是 Excel 的标准文件格式,基于 XML(可扩展标记语言)。它使用压缩的二进制格式存储数据,并可以包含多个工作表(Sheet)。
或者直接手动创建:
1 2
| data = {'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]} df = pd.DataFrame(data)
|
输出:
1 2 3 4 5 6
| A B 0 1 10 1 2 20 2 3 30 3 4 40 4 5 50
|
筛选
列筛选
假如:我们要筛选出”20经贸类4”的作业、实验、出勤、期末情况。
首先我们如果我们按字典的输入方式,输入:
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 学号 姓名 180110840516 梁家豪 18会计2 190110920132 石杨 19经贸1 200110920423 李润 20财会类3 200110920426 林小康 20财会类3 200110810629 吾佳悦 20财税类6 200110920415 胡绮 20金融类2 200110920401 陈思慧 20经贸类4 200110920402 陈特 20经贸类4 200110920404 陈雨廷 20经贸类4 200110920405 陈雨薇 20经贸类4 200110920406 戴佳妮 20经贸类4 200110920407 丁子厚 20经贸类4 200110920408 董睿滢 20经贸类4 200110920409 董欣桦 20经贸类4 200110920410 符嘉瑞 20经贸类4 200110920411 傅敬轩 20经贸类4 200110920412 巩静雯 20经贸类4 200110920413 洪旭辉 20经贸类4 200110920414 侯家馨 20经贸类4 200110920416 黄伟伟 20经贸类4 200110920417 黄卓佳 20经贸类4 200110920418 姜梦柯 20经贸类4 200110920419 荆国隆 20经贸类4 200110920420 赖砚儿 20经贸类4 ...
|
可以看到输出了一整列只有班级的值,因此我们只用直接将“班级“进行比较,无需再用for循环,就可以直接输出所有”20经贸类4“班级的信息:
1 2
| df_20_jm4 = df_zpcjd[df_zpcjd['班级'] == '20经贸类4'] print(df_20_jm4)
|
输出为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 班级 作业 实验 出勤 期末 学号 姓名 200110920401 陈思慧 20经贸类4 90 95 95 84 200110920402 陈特 20经贸类4 65 65 65 72 200110920404 陈雨廷 20经贸类4 90 85 85 44 200110920405 陈雨薇 20经贸类4 90 95 95 83 200110920406 戴佳妮 20经贸类4 90 90 90 76 200110920407 丁子厚 20经贸类4 85 90 90 57 200110920408 董睿滢 20经贸类4 97 90 90 51 200110920409 董欣桦 20经贸类4 70 80 80 66 200110920410 符嘉瑞 20经贸类4 90 90 90 68 200110920411 傅敬轩 20经贸类4 70 80 80 72 200110920412 巩静雯 20经贸类4 97 90 90 76 200110920413 洪旭辉 20经贸类4 90 95 95 85 200110920414 侯家馨 20经贸类4 92 85 85 48 200110920416 黄伟伟 20经贸类4 95 90 90 73 200110920417 黄卓佳 20经贸类4 95 90 90 75 200110920418 姜梦柯 20经贸类4 96 90 90 78 200110920419 荆国隆 20经贸类4 96 90 90 55 200110920420 赖砚儿 20经贸类4 96 95 95 84 200110920421 李鲍华 20经贸类4 95 90 90 57 200110920422 李慧婷 20经贸类4 90 90 90 67 200110920424 李奕璁 20经贸类4 96 95 95 81 200110920425 李雨萍 20经贸类4 93 90 90 77 ...
|
由次可以看到,进行直接的比较就可以筛选出想要的值。
最后再将想要的值筛选出所需列即可(如果由多个列,直接用列表即可)。
完整如下:
1 2 3
| df_20_jm4 = df_zpcjd[df_zpcjd['班级'] == '20经贸类4'] df_selected = df_20_jm4[['作业', '实验', '出勤', '期末']] print(df_selected)
|
行筛选
这里我们就可以讲到loc方法,loc方法可以帮我们精准定位我们需要的信息。
比如我想要筛选出“陈思慧”这一行,我们就可以直接输入:
1
| df_zpcjd.loc[(200110920401, '陈思慧')]
|
输出:
1 2 3 4 5 6
| 班级 20经贸类4 作业 90 实验 95 出勤 95 期末 84 Name: (200110920401, 陈思慧), dtype: object
|
筛选期末成绩小于40或者综合成绩小于60的:
1
| df_bukao=df_zpcjd[(df_zpcjd["期末"]<40) | (df_zpcjd["综合成绩"]<60)]
|
注意或是”|”还有两项之间要用括号分隔。
清洗
行删除
删除行时,通常使用 drop()
方法并指定 axis=0
(行的方向),可以通过行标签来删除。
1
| df = df.drop('行标签', axis=0)
|
列删除
1
| df = df.drop('列名', axis=1)
|
删除重复列
1
| df.loc[:, df_citygdp.nunique() > 1]
|
这里的用了loc中的nunique方法。这个方法会返回每一列中唯一值的数量。结果是一个包含每列唯一值数量的 Series
。
这个dropna方法可以删除所有包含NaN的列(或行)
Series保存
保存一个新系列,一行一列,只用Series即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| max_score = df_zpcjd['综合成绩'].max() min_score = df_zpcjd['综合成绩'].min() mean_score = df_zpcjd['综合成绩'].mean() std_score = df_zpcjd['综合成绩'].std() var_score = df_zpcjd['综合成绩'].var()
sr_cjtj = pd.Series({ '最大值': max_score, '最小值': min_score, '平均值': mean_score, '标准差': std_score, '方差': var_score }) print(sr_cjtj)
|
输出:
1 2 3 4 5 6
| 最大值 95.650000 最小值 38.400000 平均值 75.136170 标准差 11.516603 方差 132.632142 dtype: float64
|
时间计算
时间计算需要用到pandas自带的to_datetime方法:
1 2
| df_order['use_start_time'] = pd.to_datetime(df_order['use_start_time'], errors='coerce') df_order['lock_time'] = pd.to_datetime(df_order['lock_time'], errors='coerce')
|
设置 errors='coerce'
,如果无法转换为日期时间,则将该值设置为 NaT
(Not a Time)。
如果需要计算时间差值:
1
| df_order['meal_duration'] = (df_order['lock_time'] - df_order['use_start_time']).dt.total_seconds()/60
|
注意这里两个时间相减返回的是一个timedelta对象,因此可以用dt中的total_seconds方法返回差了几秒。然而如果你使用:
1
| df_order['use_start_time'].dt.total_seconds()
|
则报错,因为df_order[‘use_start_time’]为datetime对象。
如果你要提取出日期,则这么写:
1
| df_order['use_start_date'] = df_order['use_start_time'].dt.date
|
这个dt是datetime,用的是dt中的date方法。
groupby
按组分别计算,比如我需要计算每天的平均使用时间(题目是用餐时间),就可以以日期为组,计算出的时间差为值计算平均值:
1 2
| daily_avg_meal_time = df_order.groupby('use_start_date')['meal_duration'].mean()
|
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| use_start_date 2016-08-01 10.473810 2016-08-02 11.563889 2016-08-03 13.116667 2016-08-04 13.465385 2016-08-05 1109.650000 2016-08-06 9.141315 2016-08-07 9.054688 2016-08-08 10.751042 2016-08-09 9.555556 2016-08-10 12.171429 2016-08-11 10.852222 2016-08-12 693.875439 2016-08-13 10.120707
|
plot画布
首先我们要导入文件:
1 2 3
| import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False
|
我们约定俗成简写成plt。
下面两行是为了能够有中文输入,因为原本这里是不支持中文的。
我们要创建要一个画布,我们主要要有一下部件:
- 函数类型
- 函数数据
- 标题
- x轴标签、y轴标签
- x轴坐标数据、y轴坐标数据
这几个都是独立开来的,所以我们只需要的是叠加,就能完成画布制作。
折线图
1 2 3 4 5 6 7 8 9
| p1 = plt.figure(figsize=(8,20)) p1.add_subplot(3,1,1) plt.plot(range(20),ar_shuju[-3:-23:-1,-2],color='r') plt.plot(range(20),ar_shuju[-3:-23:-1,-1],color='y') plt.title('1996-2015人口变化趋势') plt.xlabel('年份') plt.ylabel('人口(万人)') plt.xticks(range(20),ar_shuju[-3:-23:-1,0],rotation=45) plt.legend(['城镇人口','乡村人口'])
|
这个例子中range(20)表示x轴的数据,ar_shuju[-3:-23:-1,-2]表示y轴数据。
饼状图
1 2 3 4
| p1.add_subplot(3,1,3) explodel = [0.01,0.01] plt.pie(ar_shuju[0,4:6],explode=explodel,labels=['城镇人口','乡村人口'],autopct='%5.2f%%') plt.title('2015年末城乡人口比例图')
|
条状图
1
| plt.bar([x轴数据...],[y轴数据...])
|
道理类似。