dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10

Chapter10:数据处理和分析:Pandas

10.1.1 从另存为CSV文件的Excel文件读取 10.1.2 从文本文件读取 10.1.3 从Excel文件读取 10.3 数据结构:Series and Data Frame 10.3.1 Series 10.3.2 Data Frame 10.4 从Web获取数据 10.5 从Data Frame提取信息 10.6 使用Pandas绘图 10.7 分组和聚合 10.7.1 Groupby方法 10.7.3 重新格式化 Data Frames

本章介绍Pandas,这是一个用于操作和分析大型(和小型)数据集的功能强大的Python包。首先要学习如何将外部文件(如Excel或文本文件)中的数据读取到Pandas中。将了解用于在称为Data Frame的类似电子表格的结构中存储日期和时间、时间序列以及组织成行和列的数据的不同数据结构。然后,将学习如何操作数据、如何提取数据子集,以及如何使用matplotlib绘制这些数据,但是要使用Pandas引入的一些新语法来帮助您使用Pandas的数据结构。

Pandas可以从以多种不同格式编写的文件中读取数据,包括以下格式:文本、CSV、Excel、JSON(JavaScript对象表示法)、固定宽度文本表、HTML(网页)以及您可以定义的更多内容。

10.1.1 从另存为CSV文件的Excel文件读取

下面看一个例子:

一些格式

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第1张图片

让我们使用Pandas读入此文件中的数据。首先,我们使用skiprows关键字参数跳过文件的前4行中包含的标题信息:

In [1]: scat = pd.read_csv('ScatMieData.csv', skiprows=4)

Pandas函数pd.read_csv()将数据读取到一个名为Data Frame的特殊Pandas对象中

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第2张图片

Data Frame是类似于电子表格的表格数据结构。它是Pandas的中央数据结构。 Data Frame scat包含一个索引列和ScatMieData.csv数据文件中的三个数据列。索引列由Pandas添加,范围从0到N -1,其中N是文件中数据点的数量。

键入scat [’Cos_theta’](一种类似于用于字典的语法)会产生相同的结果。可以像NumPy数组一样通过索引来访问单个元素和切片:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第3张图片

在上面的示例中,我们通过设置skiprows = 4忽略了前4行中包含的标题数据。假设我们要读入这四行中的信息。

532f1ce5809c36712f93f0417a86d491.png

我们使用关键字nrows并将其设置为等于4,以便Pandas仅读取文件的前4行,该行包含标题信息。我们还设置head = None,因为这4行没有单独的标题信息。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第4张图片

注意:head [i] [j]索引中,第一个代表列,第二个代表行。

图像输出代码

1 import numpy as np
2 import matplotlib.pyplot as plt
3 import pandas as pd
4
5 # Read in data
6 head = pd.read_table('ScatMieData.csv', sep='=', nrows=4,
7 comment=',', header=None)
8 scat = pd.read_csv('ScatMieData.csv', skiprows=4)
9
10 theta = (180./np.pi)*np.arccos(scat.Cos_theta)
11
12 plt.close('all')
13 fig, ax = plt.subplots(figsize=(6, 4))
14
15 ax.semilogy(theta, scat.F1, 'o', color='black', label="F1")
16 ax.semilogy(theta, scat.F2, 's', mec='black', mfc='white',
17 zorder=-1, label="F2")
18 ax.legend(loc="lower left")
19 ax.set_xlabel("theta (degrees)")
20 ax.set_ylabel("intensity")
21 for i in range(4):
22 ax.text(0.95, 0.9-i/18, "{} = {}"
23 .format(head[0][i], head[1][i]),
24 ha='right', fontsize=10, transform=ax.transAxes)
25 fig.tight_layout()
26 fig.savefig('ScatMiePlot.pdf')

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第5张图片

10.1.2 从文本文件读取

数据文件的最常见形式可能是文本文件,由包含用空格,制表符或其他字符分隔的数据列组成。读取这些类型的文件的是read_table(),read_table()与read_csv()完全相同,只是它添加了关键字sep,该关键字使您可以指定如何分隔数据列。实际上,read_table(sep =’,’)完全等同于read_csv()。

举例说明:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第6张图片

表中的数量以地球为参考。每列与前一列之间以可变数量的空格分隔。Pandas处理此问题的方式是通过设置sep =’S +’。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第7张图片

表总结了我们在上面讨论的读取函数中使用的一些关键字参数。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第8张图片

10.1.3 从Excel文件读取

下面看一个例子:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第9张图片

使用Pandas从Excel文件中读取数据非常简单:

bp = pd.read_excel('BloodPressure.xlsx',usecols='A:E')

关键字参数usecols=‘A:E’告诉Pandas仅读取A到E列;忽略任何其他列中的数据。如果我们只想读取Pulse数据,我们可以为关键字参数编写usecols=‘A:B,E’。但正如编写的那样,Pandas将A列到E列读入名为BP的Data Frame对象,

用于读取表格数据文件的Pandas函数总结:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第10张图片

10.3 数据结构:Series and Data Frame

Pandas有两个主要的数据结构:Series和Data Frame。它们构成了大多数使用Pandas的活动的基础。我们已经在上文中见过Data Frame,并对其最基本的属性和用法有了一些了解。Series对象是一维Data Frame。Series和Data Frames都广泛使用NumPy数组,但Series允许更多用途的索引方式。

10.3.1 Series

Pandas Series是一维类似数组的数据结构,由NumPy数组和称为索引的相关数据标签数组组成。我们可以使用Pandas Series函数创建Series,该函数将列表、字典或NumPy数组转换为Pandas Series。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第11张图片

显示的IPython输出分两列,左侧是索引列,右侧是Series的值。参数可以是列表、迭代器或NumPy数组。 在本例中,系列的值是浮点数。索引从0到N−1,其中N是数据点的数量。访问单个元素和切片的方式与访问列表和NumPy数组的方式相同。

Series可以指定索引:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第12张图片

可以将Pandas转换为字典:

b5b0c5674c7e52d2d7b395e9f29bc6e3.png

可以将字典转换为Series:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第13张图片

10.3.2 Data Frame

我们在上文中介绍了Data Frame,这是一种类似于电子表格的二维数据结构。在那里我们了解到,我们可以使用列标签访问Data Frame的一列,如Planets[‘quality’]以获取质量列中所有行星的质量,或使用单个Data Frame单元格(如 planets[’mass’] [’Mars’])来获取单个行星的质量。

创建Data Frame

到目前为止,我们使用的Data Frame是在我们从文本、CSV或Excel文件中读取数据时为我们创建的。或者,您可以使用Pandas Data Frame例程创建Data Frame。您几乎可以使用任何类似列表的对象作为输入,包括列表、NumPy数组或字典。也许最简单的方法是使用字典。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第14张图片

可以使用COLUMNS关键字参数强制列按所需的顺序显示。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第15张图片

可以创建一个包含空列的Data Frame,并在以后填充数据。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第16张图片

填充数据:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第17张图片

10.4 从Web获取数据

Pandas拥有从网络上抓取数据的广泛工具。

1 import pandas as pd
2
3 url1 = 'http://www.bankofcanada.ca/'
4 url2 = 'valet/observations/group/FX_RATES_DAILY/csv?start_date='
5 start_date = '2017-01-03' # Earliest start date is 2017-01-03
6 url = url1+url2+start_date # Complete url to download csv file
7 # Read in rates for different currencies for a range of dates
8 rates = pd.read_csv(url, skiprows=39, index_col='date')
9 rates.index = pd.to_datetime(rates.index) # assures data type
10 # Get number of days & number of currences from shape of rates
11 days, currencies = rates.shape
12 # Read in the currency codes & strip off extraneous part
13 codes = pd.read_csv(url, skiprows=10, usecols=[0, 2],
14 nrows=currencies)
15 for i in range(currencies):
16 codes.iloc[i, 1] = codes.iloc[i, 1].split(' to Canadian')[0]
17 # Report exchange rates for the most most recent date available
18 date = rates.index[-1] # most recent date available
19 print('nCurrency values on {0}'.format(date))
20 for (code, rate) in zip(codes.iloc[:, 1], rates.loc[date]):
21 print("{0:20s}  Can$ {1:8.6g}".format(code, rate))

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第18张图片

我们在这里所做的只说明了操作和分析的一个简单特性:用于从Web上抓取数据的DAS。Pandas内部还存在更多的网络抓取工具。它们范围广泛且功能强大,可以与其他包(如urllib3)配合使用,以提取Web上存在的几乎任何数据。

10.5 从Data Frame提取信息

一旦我们将数据组织到Data Frame中,我们就可以使用Pandas的工具以各种方式提取和汇总其中包含的数据。

我们再来看上文的例子:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第19张图片

Pandas可以很容易地对数据进行分类。例如,要按质量递增的顺序列出行星:

a2bdd5d9ade33f980d31123ba20036bf.png

要生成相同的表,但从最高质量到最低质量,请加入关键字ascending=False。

如何用条件索引(布尔语句)来获得数据列表:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第20张图片

如何添加数据进入Data Frame中:(以“体积”为例)

6600069219b85d896c5c8c9aad7ecbce.png

Pandas可以为Data Frame中的数据计算标准统计量:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第21张图片

Pandas 的 Data Frame and Series.的统计方法:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第22张图片

10.6 使用Pandas绘图

Pandas构建在matplotlib包的基础上,添加了Pandas特有的一些功能。在绘制来自Pandas Series或Data Frame的数据时,如果没有另外指定x数据,matplotlib的Plot函数将使用索引作为x数据。

例如,我们可以用以下简单的命令从行星数据框中获得每个行星的相对引力的图形显示:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第23张图片

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第24张图片

plot(bp)[上]和bp.plot()[下]区别

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第25张图片

可以看出X坐标的格式好了一些,所以我们推荐用bp.plot()。

绘制多数据同一坐标值散点图

1 import matplotlib.pyplot as plt
2 import pandas as pd
3 import matplotlib.dates as mdates
4 from datetime import datetime
5
6 # Read in data
7 bp = pd.read_excel('BloodPressure.xlsx', usecols='A:E',
8 parse_dates=[['Date', 'Time']])
9 bp = bp.set_index('Date_Time')
10 # Divide data into AM and PM sets
11 diaAM = bp.loc[bp.index.hour < 12, 'BP_dia']
12 diaPM = bp.loc[bp.index.hour >= 12, 'BP_dia']
13 sysAM = bp.loc[bp.index.hour < 12, 'BP_sys']
14 sysPM = bp.loc[bp.index.hour >= 12, 'BP_sys']
15 PulseAM = bp.loc[bp.index.hour < 12, 'Pulse']
16 PulsePM = bp.loc[bp.index.hour >= 12, 'Pulse']
17 # Set up figure with 2 subplots and plot BP data
18
19 fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True,
20 gridspec_kw={'height_ratios': [2, 1]},
21 figsize=(10, 6))
22 fig.subplots_adjust(left=0.065, right=0.99, hspace=0.06)
23 sysPM.plot(ax=ax1, marker='o', ms=3, lw=0, color='C1',
24 label='systolic PM')
25 sysAM.plot(ax=ax1, marker='o', ms=3, lw=0, color='C1',
26 mfc='white', label='systolic AM')
27 diaPM.plot(ax=ax1, marker='o', ms=3, lw=0, color='C0',
28 label='diastolic PM')
29 diaAM.plot(ax=ax1, marker='o', ms=3, lw=0, color='C0',
30 mfc='white', label='diastolic AM')
31 # Average values of blood pressures with arrows labeling them
32 dtlab = datetime(2017, 6, 29)
33 bpavgs = (sysAM.mean(), sysPM.mean(), diaAM.mean(),
34 diaPM.mean())
35 ytext = ('bottom', 'top')
36 tavgs = ('AM average = {0:0.0f}'.format(bpavgs[0]),
37 'PM average = {0:0.0f}'.format(bpavgs[1]),
38 'AM average = {0:0.0f}'.format(bpavgs[2]),
39 'PM average = {0:0.0f}'.format(bpavgs[3]))
40 aprops = dict(facecolor='black', width=1, headlength=5,
41 headwidth=5)
42 for i, bpa in enumerate(bpavgs):
43 ax1.annotate(tavgs[i], xy=(dtlab, bpa),
44 xytext=((15, (-1)**(i % 2)*15)),
45 textcoords='offset points',
46 arrowprops=aprops, ha='left',
47 va=ytext[i % 2])
48 # Lines indicating average blood pressures
49 ax1.axhline(y=sysPM.mean(), color='C1', lw=0.75, zorder=-1)
50 ax1.axhline(y=sysAM.mean(), color='C1', dashes=(5, 2),
51 lw=0.75, zorder=-1)
52 ax1.axhline(y=diaPM.mean(), color='C0', lw=0.75, zorder=-1)
53 ax1.axhline(y=diaAM.mean(), color='C0', dashes=(5, 2),
54 lw=0.75, zorder=-1)
55 # Formatting top graph
56 ax1.set_title('Blood pressure & pulse log')
57 ax1.set_ylabel('blood pressure (mm-Hg)')
58 ax1.legend(loc=(0.37, 0.43))
59 ax1.grid(dashes=(1, 2))
60 # Plot pulse
61 PulsePM.plot(ax=ax2, marker='o', ms=3, lw=0, color='k',
62 label='PM')
63 PulseAM.plot(ax=ax2, marker='o', ms=3, lw=0, color='k',
64 mfc='white', label='AM')
65 # Average values of pulse with arrows labeling them
66 Pulseavgs = (PulseAM.mean(), PulsePM.mean())
67 tavgs = ('AM average = {0:0.0f}'.format(Pulseavgs[0]),
68 'PM average = {0:0.0f}'.format(Pulseavgs[1]))
69 for i, pulse in enumerate(Pulseavgs):
70 ax2.annotate(tavgs[i], xy=(dtlab, pulse),
71 xytext=((15, -(-1)**(i)*15)),
72 textcoords='offset points',
73 arrowprops=aprops, ha='left',
74 va=ytext[-i-1])
75
76 ax2.axhline(y=PulsePM.mean(), color='k', lw=0.75, zorder=-1)
77 ax2.axhline(y=PulseAM.mean(), color='k', dashes=(5, 2),
78 lw=0.75, zorder=-1)
79 # Formatting bottom graph
80 week = mdates.WeekdayLocator(byweekday=mdates.SU)
81 day = mdates.DayLocator()
82 ax2.xaxis.set_major_locator(week)
83 ax2.xaxis.set_minor_locator(day)
84 ax2.set_xlabel('')
85 ax2.set_ylabel('pulse (/min)')
86 ax2.legend(loc=(0.4, 0.7))
87 ax2.grid(dashes=(1, 2))
88
89 fig.tight_layout()
90 fig.show()
91 fig.savefig('./figures/BloodPressure.pdf')

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第26张图片

10.7 分组和聚合

Pandas允许您以有用和强大的方式对数据进行分组和分析子组。

例子:列出了1555个数据行和10个数据列。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第27张图片

让我们熟悉一下EWR Data Frame。你可能会想知道航班状态的可能性是什么。您可以使用value_counts()方法查找并获取一些附加信息。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第28张图片

还有很多获取信息的语法和关键字,不一一列举。

10.7.1 Groupby方法

现在假设我们想知道按航站楼细分的每个航班的状态。为此,我们需要一个更复杂的工具:groupby。以下是它的工作原理:

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第29张图片

在这种情况下,我们想知道每个航班的状态,因此ewr[‘status’]在上面的命令中排在第一位。接下来,我们希望Status按终端进行细分,因此我们添加了带有参数ewr[‘Terminal’]的方法groupby。最后,我们想知道每个类别有多少航班,所以我们添加了方法value_counts()。

10.7.3 重新格式化 Data Frames

检查一下ewr Data Frame的不同列的数据类型。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第30张图片

我们注意到,离开、到达时间和预定时间没有格式化为DateTime对象。要将它们转换为DateTime对象,我们使用Pandas的Apply方法,该方法将函数应用于Data Frame的列(默认设置)或行(通过设置关键字axis=0)。在这里,我们使用Pandas函数pd.to_datetime。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第31张图片

接下来我们设定日期。首先,我们使用DateTime替换方法将所有航班的年、月、日重置为出发日期:2018-05-16。

05c36f632021d39d74d4c7a3ea8dd84a.png

最后,我们向Scheduled和Arrival_time列中的那些日期添加一天,这些日期在具有此代码段的相应S_day和A_day列中为1。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第32张图片

最后让我们计算实际Arrival_time与计划到达时间之间的时差。

dataframe 列转成行 python_[科学与工程Python简介]——Chapter 10_第33张图片

你可能感兴趣的:(dataframe,列转成行,python)