数据操作

与过滤或转换数组和表中的数据相关的食谱。

查看 计算函数 以获取所有可用计算函数的完整列表

计算数组的平均值/最小值/最大值

Arrow 提供了可以应用于数组的计算函数。这些计算函数通过 pyarrow.compute 模块公开。

给定一个包含 100 个数字的数组,从 0 到 99

print(f"{arr[0]} .. {arr[-1]}")
0 .. 99

我们可以使用 pyarrow.compute.mean() 函数计算 mean

import pyarrow.compute as pc

mean = pc.mean(arr)
print(mean)
49.5

以及使用 pyarrow.compute.min_max() 函数计算 minmax

import pyarrow.compute as pc

min_max = pc.min_max(arr)
print(min_max)
[('min', 0), ('max', 99)]

计算元素出现的次数

Arrow 提供了可以应用于数组的计算函数,这些计算函数通过 pyarrow.compute 模块公开。

给定一个数组,其中包含从 0 到 9 的所有数字,重复 10 次

print(f"LEN: {len(nums_arr)}, MIN/MAX: {nums_arr[0]} .. {nums_arr[-1]}")
LEN: 100, MIN/MAX: 0 .. 9

我们可以使用 pyarrow.compute.value_counts() 函数计算数组中所有条目的出现次数

import pyarrow.compute as pc

counts = pc.value_counts(nums_arr)
for pair in counts:
    print(pair)
[('values', 0), ('counts', 10)]
[('values', 1), ('counts', 10)]
[('values', 2), ('counts', 10)]
[('values', 3), ('counts', 10)]
[('values', 4), ('counts', 10)]
[('values', 5), ('counts', 10)]
[('values', 6), ('counts', 10)]
[('values', 7), ('counts', 10)]
[('values', 8), ('counts', 10)]
[('values', 9), ('counts', 10)]

将算术函数应用于数组。

pyarrow.compute 中的计算函数还包括常见的转换,例如算术函数。

给定一个包含 100 个数字的数组,从 0 到 99

print(f"{arr[0]} .. {arr[-1]}")
0 .. 99

我们可以使用 pyarrow.compute.multiply() 函数将所有值乘以 2

import pyarrow.compute as pc

doubles = pc.multiply(arr, 2)
print(f"{doubles[0]} .. {doubles[-1]}")
0 .. 198

将表追加到现有表

如果您将数据拆分到两个不同的表中,则可以将它们的行列连接到一个表中。

如果我们有奥斯卡提名列表,它们被分成两个不同的表

import pyarrow as pa

oscar_nominations_1 = pa.table([
  ["Meryl Streep", "Katharine Hepburn"],
  [21, 12]
], names=["actor", "nominations"])

oscar_nominations_2 = pa.table([
  ["Jack Nicholson", "Bette Davis"],
  [12, 10]
], names=["actor", "nominations"])

我们可以使用 pyarrow.concat_tables() 将它们组合成一个表

oscar_nominations = pa.concat_tables([oscar_nominations_1,
                                      oscar_nominations_2])
print(oscar_nominations)
pyarrow.Table
actor: string
nominations: int64
----
actor: [["Meryl Streep","Katharine Hepburn"],["Jack Nicholson","Bette Davis"]]
nominations: [[21,12],[12,10]]

注意

默认情况下,追加两个表是一个零拷贝操作,不需要复制或重写数据。由于表是由 pyarrow.ChunkedArray 组成,因此结果将是一个包含多个块的表,每个块都指向已追加的原始数据。在某些情况下,Arrow 可能需要将数据从一种类型转换为另一种类型(如果 promote=True)。在这种情况下,数据将需要被复制,并且会产生额外的成本。

向现有表添加列

如果您有一个表,可以使用 pyarrow.Table.append_column() 扩展其列

假设我们有一个表,其中包含每个女演员的奥斯卡提名

import pyarrow as pa

oscar_nominations = pa.table([
  ["Meryl Streep", "Katharine Hepburn"],
  [21, 12]
], names=["actor", "nominations"])

print(oscar_nominations)
pyarrow.Table
actor: string
nominations: int64
----
actor: [["Meryl Streep","Katharine Hepburn"]]
nominations: [[21,12]]

可以使用 pyarrow.Table.append_column() 追加一个额外的列来跟踪提名获奖年份

oscar_nominations = oscar_nominations.append_column(
  "wonyears",
  pa.array([
    [1980, 1983, 2012],
    [1934, 1968, 1969, 1982]
  ])
)

print(oscar_nominations)
pyarrow.Table
actor: string
nominations: int64
wonyears: list<item: int64>
  child 0, item: int64
----
actor: [["Meryl Streep","Katharine Hepburn"]]
nominations: [[21,12]]
wonyears: [[[1980,1983,2012],[1934,1968,1969,1982]]]

替换现有表中的列

如果您有一个表,可以使用 pyarrow.Table.set_column() 替换现有列

假设我们有一个表,其中包含某一天在超市销售的商品信息。

import pyarrow as pa

sales_data = pa.table([
  ["Potato", "Bean", "Cucumber", "Eggs"],
  [21, 12, 10, 30]
], names=["item", "amount"])

print(sales_data)
pyarrow.Table
item: string
amount: int64
----
item: [["Potato","Bean","Cucumber","Eggs"]]
amount: [[21,12,10,30]]

可以使用 pyarrow.Table.set_column() 替换索引 1 中的现有列 amount,以更新销售额

new_sales_data = sales_data.set_column(
  1,
  "new_amount",
  pa.array([30, 20, 15, 40])
)

print(new_sales_data)
pyarrow.Table
item: string
new_amount: int64
----
item: [["Potato","Bean","Cucumber","Eggs"]]
new_amount: [[30,20,15,40]]

对表进行分组

如果您有一个需要按特定键分组的表,可以使用 pyarrow.Table.group_by(),然后进行聚合操作 pyarrow.TableGroupBy.aggregate()。了解有关 groupby 操作的更多信息 此处

例如,假设我们有一些数据,其中包含一组特定的键以及与该键关联的值。我们希望按这些键对数据进行分组,并应用一个聚合函数(如 sum)来评估每个唯一键有多少个项目。

import pyarrow as pa

table = pa.table([
     pa.array(["a", "a", "b", "b", "c", "d", "e", "c"]),
     pa.array([11, 20, 3, 4, 5, 1, 4, 10]),
    ], names=["keys", "values"])

print(table)
pyarrow.Table
keys: string
values: int64
----
keys: [["a","a","b","b","c","d","e","c"]]
values: [[11,20,3,4,5,1,4,10]]

现在我们应用 groupby 操作。该表将按字段 key 进行分组,并在列 values 上应用聚合操作 sum。请注意,聚合操作与列名配对。

aggregated_table = table.group_by("keys").aggregate([("values", "sum")])

print(aggregated_table)
pyarrow.Table
keys: string
values_sum: int64
----
keys: [["a","b","c","d","e"]]
values_sum: [[31,7,15,1,4]]

如果您仔细观察,新表将返回聚合后的列作为 values_sum,它是由列名和聚合操作名组成的。

聚合操作可以应用于选项。让我们以一个案例为例,其中我们的数据集中包含空值,但我们希望计算唯一组的计数,不包括空值。

可以形成一个示例数据集,如下所示。

import pyarrow as pa

table = pa.table([
      pa.array(["a", "a", "b", "b", "b", "c", "d", "d", "e", "c"]),
      pa.array([None, 20, 3, 4, 5, 6, 10, 1, 4, None]),
      ], names=["keys", "values"])

print(table)
pyarrow.Table
keys: string
values: int64
----
keys: [["a","a","b","b","b","c","d","d","e","c"]]
values: [[null,20,3,4,5,6,10,1,4,null]]

让我们应用一个聚合操作 count,该操作具有排除空值的选项。

import pyarrow.compute as pc

grouped_table = table.group_by("keys").aggregate(
  [("values",
  "count",
  pc.CountOptions(mode="only_valid"))]
)

print(grouped_table)
pyarrow.Table
keys: string
values_count: int64
----
keys: [["a","b","c","d","e"]]
values_count: [[1,3,1,2,1]]

对表进行排序

让我们讨论如何对表进行排序。我们可以根据给定列的值对表进行排序。数据可以按 ascendingdescending 进行排序。

准备数据;

import pyarrow as pa

table = pa.table([
      pa.array(["a", "a", "b", "b", "b", "c", "d", "d", "e", "c"]),
      pa.array([15, 20, 3, 4, 5, 6, 10, 1, 14, 123]),
      ], names=["keys", "values"])

print(table)
pyarrow.Table
keys: string
values: int64
----
keys: [["a","a","b","b","b","c","d","d","e","c"]]
values: [[15,20,3,4,5,6,10,1,14,123]]

然后使用 pyarrow.Table.sort_by() 应用排序;

sorted_table = table.sort_by([("values", "ascending")])

print(sorted_table)
pyarrow.Table
keys: string
values: int64
----
keys: [["d","b","b","b","c","d","e","a","a","c"]]
values: [[1,3,4,5,6,10,14,15,20,123]]

在数组中搜索与谓词匹配的值

如果您必须在 Arrow 数组中查找与谓词匹配的值,pyarrow.compute 模块提供了多种方法,可用于查找您要查找的值。

例如,给定一个包含从 0 到 9 的数字的数组,如果我们只想查找大于 5 的数字,我们可以使用 pyarrow.compute.greater() 方法,并获取符合我们谓词的元素

import pyarrow as pa
import pyarrow.compute as pc

arr = pa.array(range(10))
gtfive = pc.greater(arr, 5)

print(gtfive.to_string())
[
  false,
  false,
  false,
  false,
  false,
  false,
  true,
  true,
  true,
  true
]

此外,我们可以使用 pyarrow.compute.filter() 过滤数组,以仅获取与我们谓词匹配的条目

filtered_array = pc.filter(arr, gtfive)
print(filtered_array)
[
  6,
  7,
  8,
  9
]

使用掩码过滤数组

在许多情况下,当您在数组中搜索某些内容时,您将最终得到一个掩码,它告诉您搜索匹配值的那些位置。

例如,在一个包含四个项目的数组中,我们可能有一个掩码,它只匹配第一个和最后一个项目

import pyarrow as pa

array = pa.array([1, 2, 3, 4])
mask = pa.array([True, False, False, True])

然后,我们可以使用 pyarrow.Array.filter() 根据掩码过滤数组,以获取一个仅包含与掩码匹配的值的新数组

filtered_array = array.filter(mask)
print(filtered_array)
[
  1,
  4
]

pyarrow.compute 中的大多数搜索函数将生成一个掩码作为输出,因此您可以使用它们来过滤数组,以获取由该函数找到的值。

例如,我们可以使用 pyarrow.compute.equal() 过滤数组,以获取等于 2 的值

import pyarrow.compute as pc

filtered_array = array.filter(pc.equal(array, 2))
print(filtered_array)
[
  2
]