表格

表格是表示数据集的基本对象类型。表格可以从两个角度来理解: * 一组命名的列序列,每一列描述了数据集中所有条目的一个方面,或者 * 一组行序列,每一行包含数据集中单个条目的所有信息。

为了使用表格,需要导入名为 datascience 的模块,这是一个为本教材创建的模块。

[In ]:
import numpy as np
np.set_printoptions(threshold=50)
path_data = '../../assets/data/'
[In ]:
from datascience import *

可以使用 Table 函数创建空表。空表很有用,因为它可以扩展以包含新的行和列。

[In ]:
Table()

表格上的 with_columns 方法构造一个带有附加标记列的新表格。表格的每一列都是一个数组。要在表格中添加一个新列,使用标签和数组调用 with_columns。(with_column 方法可以达到同样的效果。)

下面,我们每个示例都从一个没有列的空表开始。

[In ]:
Table().with_columns('Number of petals', make_array(8, 34, 5))
Number of petals
8
34
5

要添加两个(或更多)新列,请为每列提供标签和数组。所有列必须具有相同的长度,否则将出错。

[In ]:
Table().with_columns(
    'Number of petals', make_array(8, 34, 5),
    'Name', make_array('lotus', 'sunflower', 'rose')
)
Number of petals | Name
8                | lotus
34               | sunflower
5                | rose

我们可以给这个表格命名,然后用另一列扩展它。

[In ]:
flowers = Table().with_columns(
    'Number of petals', make_array(8, 34, 5),
    'Name', make_array('lotus', 'sunflower', 'rose')
)

flowers.with_columns(
    'Color', make_array('pink', 'yellow', 'red')
)
Number of petals | Name      | Color
8                | lotus     | pink
34               | sunflower | yellow
5                | rose      | red

with_columns 方法每次调用时都会创建一个新表格,因此原始表格不受影响。例如,表格 flowers 仍然只有创建时的两列。

[In ]:
flowers
Number of petals | Name
8                | lotus
34               | sunflower
5                | rose

以这种方式创建表格需要大量输入。如果数据已经在某处输入好了,通常可以用 Python 将其读入表格,而不是逐单元输入。

通常,表格是从包含逗号分隔值的文件创建的。此类文件称为 CSV 文件。

下面,我们使用 Table 方法 read_table 读取一个 CSV 文件,该文件包含 Minard 在他的拿破仑俄国战役图表中使用的一些数据。这些数据被放入名为 minard 的表格中。

[In ]:
minard = Table.read_table(path_data + 'minard.csv')
minard
Longitude | Latitude | City        | Direction | Survivors
32        | 54.8     | Smolensk    | Advance   | 145000
33.2      | 54.9     | Dorogobouge | Advance   | 140000
34.4      | 55.5     | Chjat       | Advance   | 127100
37.6      | 55.8     | Moscou      | Advance   | 100000
34.3      | 55.2     | Wixma       | Retreat   | 55000
32        | 54.6     | Smolensk    | Retreat   | 24000
30.4      | 54.4     | Orscha      | Retreat   | 20000
26.8      | 54.3     | Moiodexno   | Retreat   | 12000

我们将使用这个小型表格来演示一些有用的 Table 方法。然后,我们将在更大的数据表格上使用这些方法,并开发其他方法。

表格的大小

num_columns 方法给出表格中的列数,num_rows 方法给出行数。

[In ]:
minard.num_columns
5
[In ]:
minard.num_rows
8

列标签

labels 方法可用于列出所有列的标签。对于 minard 来说这没什么大用,但对于那些大到屏幕无法显示所有列的表格来说,这可能非常有用。

[In ]:
minard.labels
('Longitude', 'Latitude', 'City', 'Direction', 'Survivors')

我们可以使用 relabeled 方法来更改列标签。这会创建一个新表格,而 minard 保持不变。

[In ]:
minard.relabeled('City', 'City Name')
Longitude | Latitude | City Name   | Direction | Survivors
32        | 54.8     | Smolensk    | Advance   | 145000
33.2      | 54.9     | Dorogobouge | Advance   | 140000
34.4      | 55.5     | Chjat       | Advance   | 127100
37.6      | 55.8     | Moscou      | Advance   | 100000
34.3      | 55.2     | Wixma       | Retreat   | 55000
32        | 54.6     | Smolensk    | Retreat   | 24000
30.4      | 54.4     | Orscha      | Retreat   | 20000
26.8      | 54.3     | Moiodexno   | Retreat   | 12000

然而,这个方法不会改变原始表格。

[In ]:
minard
Longitude | Latitude | City        | Direction | Survivors
32        | 54.8     | Smolensk    | Advance   | 145000
33.2      | 54.9     | Dorogobouge | Advance   | 140000
34.4      | 55.5     | Chjat       | Advance   | 127100
37.6      | 55.8     | Moscou      | Advance   | 100000
34.3      | 55.2     | Wixma       | Retreat   | 55000
32        | 54.6     | Smolensk    | Retreat   | 24000
30.4      | 54.4     | Orscha      | Retreat   | 20000
26.8      | 54.3     | Moiodexno   | Retreat   | 12000

一种常见的做法是将新表格赋值给原始名称 minard,这样以后所有使用 minard 的地方都指向重新标记后的表格。

[In ]:
minard = minard.relabeled('City', 'City Name')
minard
Longitude | Latitude | City Name   | Direction | Survivors
32        | 54.8     | Smolensk    | Advance   | 145000
33.2      | 54.9     | Dorogobouge | Advance   | 140000
34.4      | 55.5     | Chjat       | Advance   | 127100
37.6      | 55.8     | Moscou      | Advance   | 100000
34.3      | 55.2     | Wixma       | Retreat   | 55000
32        | 54.6     | Smolensk    | Retreat   | 24000
30.4      | 54.4     | Orscha      | Retreat   | 20000
26.8      | 54.3     | Moiodexno   | Retreat   | 12000

访问列中的数据

我们可以使用列的标签来访问该列中的数据数组。

[In ]:
minard.column('Survivors')
array([145000, 140000, 127100, 100000,  55000,  24000,  20000,  12000])

这 5 列的索引为 0、1、2、3 和 4。Survivors 列也可以通过其列索引访问。

[In ]:
minard.column(4)
array([145000, 140000, 127100, 100000,  55000,  24000,  20000,  12000])

数组中的 8 个元素的索引为 0、1、2 等,一直到 7。与任何数组一样,可以使用 item 访问列中的元素。

[In ]:
minard.column(4).item(0)
145000
[In ]:
minard.column(4).item(5)
24000

操作列中的数据

因为列是数组,我们可以对它们使用数组操作来发现新信息。例如,我们可以创建一个新列,其中包含斯摩棱斯克之后每个城市的幸存者百分比。

[In ]:
initial = minard.column('Survivors').item(0)
minard = minard.with_columns(
    'Percent Surviving', minard.column('Survivors')/initial
)
minard
Longitude | Latitude | City Name   | Direction | Survivors | Percent Surviving
32        | 54.8     | Smolensk    | Advance   | 145000    | 1
33.2      | 54.9     | Dorogobouge | Advance   | 140000    | 0.965517
34.4      | 55.5     | Chjat       | Advance   | 127100    | 0.876552
37.6      | 55.8     | Moscou      | Advance   | 100000    | 0.689655
34.3      | 55.2     | Wixma       | Retreat   | 55000     | 0.37931
32        | 54.6     | Smolensk    | Retreat   | 24000     | 0.165517
30.4      | 54.4     | Orscha      | Retreat   | 20000     | 0.137931
26.8      | 54.3     | Moiodexno   | Retreat   | 12000     | 0.0827586

为了使新列中的比例显示为百分比,我们可以使用带有 PercentFormatter 选项的 set_format 方法。set_format 方法接受 Formatter 对象,这些对象可用于日期(DateFormatter)、货币(CurrencyFormatter)、数字和百分比。

[In ]:
minard.set_format('Percent Surviving', PercentFormatter)
Longitude | Latitude | City Name   | Direction | Survivors | Percent Surviving
32        | 54.8     | Smolensk    | Advance   | 145000    | 100.00%
33.2      | 54.9     | Dorogobouge | Advance   | 140000    | 96.55%
34.4      | 55.5     | Chjat       | Advance   | 127100    | 87.66%
37.6      | 55.8     | Moscou      | Advance   | 100000    | 68.97%
34.3      | 55.2     | Wixma       | Retreat   | 55000     | 37.93%
32        | 54.6     | Smolensk    | Retreat   | 24000     | 16.55%
30.4      | 54.4     | Orscha      | Retreat   | 20000     | 13.79%
26.8      | 54.3     | Moiodexno   | Retreat   | 12000     | 8.28%

选择列集

select 方法创建一个只包含指定列的新表格。

[In ]:
minard.select('Longitude', 'Latitude')
Longitude | Latitude
32        | 54.8
33.2      | 54.9
34.4      | 55.5
37.6      | 55.8
34.3      | 55.2
32        | 54.6
30.4      | 54.4
26.8      | 54.3

同样可以使用列索引代替标签进行选择。

[In ]:
minard.select(0, 1)
Longitude | Latitude
32        | 54.8
33.2      | 54.9
34.4      | 55.5
37.6      | 55.8
34.3      | 55.2
32        | 54.6
30.4      | 54.4
26.8      | 54.3

使用 select 的结果是一个新表格,即使你只选择一列也是如此。

[In ]:
minard.select('Survivors')
Survivors
145000
140000
127100
100000
55000
24000
20000
12000

注意结果是表格,与 column 的结果不同,后者返回的是一个数组。

[In ]:
minard.column('Survivors')
array([145000, 140000, 127100, 100000,  55000,  24000,  20000,  12000])

另一种创建包含一组列的新表格的方法是 drop 掉你不需要的列。

[In ]:
minard.drop('Longitude', 'Latitude', 'Direction')
City Name   | Survivors | Percent Surviving
Smolensk    | 145000    | 100.00%
Dorogobouge | 140000    | 96.55%
Chjat       | 127100    | 87.66%
Moscou      | 100000    | 68.97%
Wixma       | 55000     | 37.93%
Smolensk    | 24000     | 16.55%
Orscha      | 20000     | 13.79%
Moiodexno   | 12000     | 8.28%

selectdrop 都不会改变原始表格。相反,它们创建共享相同数据的新的小表格。原始表格得以保留这一事实非常有用!你可以生成多个只考虑某些列的不同表格,而不必担心一个分析会影响另一个。

[In ]:
minard
Longitude | Latitude | City Name   | Direction | Survivors | Percent Surviving
32        | 54.8     | Smolensk    | Advance   | 145000    | 100.00%
33.2      | 54.9     | Dorogobouge | Advance   | 140000    | 96.55%
34.4      | 55.5     | Chjat       | Advance   | 127100    | 87.66%
37.6      | 55.8     | Moscou      | Advance   | 100000    | 68.97%
34.3      | 55.2     | Wixma       | Retreat   | 55000     | 37.93%
32        | 54.6     | Smolensk    | Retreat   | 24000     | 16.55%
30.4      | 54.4     | Orscha      | Retreat   | 20000     | 13.79%
26.8      | 54.3     | Moiodexno   | Retreat   | 12000     | 8.28%

我们上面使用的所有方法都可以应用于任何表格。