
在使用pyarrow处理数据时,我们经常需要根据某些列的值对数据进行分组,并计算每组的聚合统计量。然而,当分组键(grouping key)中包含列表(list)类型的数据时,pyarrow的group_by方法会抛出arrownotimplementederror,提示“keys of type list
考虑以下原始数据结构,其中ListData列是整数列表:
import pyarrow as pa
import pyarrow.compute as pc
test_table_orig = pa.table([
pa.array(["a", "a", "a", "a", "a", "b", "b", "b", "b", "b", "c", "c", "c", "c", "c", "d", "d", "d", "d", "e", "e", "e", "e", "e", "f", "f", "f", "f", "f", "f"]),
pa.array([[1,1,1,1], [2,0,1,2], [3,2,1,0], [4,3,2,1], [4,3,2,1], [1,2,3,4], [1,2,3,4], [1,2,3,4], [1,2,3,4], [1,2,3,4], [5,4,3,2], [5,4,3,2], [5,4,3,2], [5,4,3,2], [4,3,2,1], [6,5,4,3], [6,5,4,3], [8,7,6,5], [9,8,7,6], [7,6,5,4], [7,6,5,4], [7,6,5,4], [7,6,5,4], [10,11,12,13], [11,12,13,14], [12,13,14,15], [33,44,55,66], [22,33,44,55], [55,66,77,88], [22,33,44,55]])
], names=["ID", "ListData"])
# 尝试直接分组聚合会导致错误
try:
test_table_orig.group_by(['ID','ListData']).aggregate([('ListData','count')]).to_pandas()
except pa.lib.ArrowNotImplementedError as e:
print(f"Error: {e}")
# Error: Keys of type list<item: int64>上述代码清晰地展示了PyArrow对列表类型作为分组键的限制。
一种常见的变通方法是将列表数据转换为字符串表示。由于字符串是可哈希的标量类型,PyArrow可以成功地对其进行分组聚合。
test_table_string = pa.table([
pa.array(["a", "a", "a", "a", "a", "b", "b", "b", "b", "b", "c", "c", "c", "c", "c", "d", "d", "d", "d", "e", "e", "e", "e", "e", "f", "f", "f", "f", "f", "f"]),
pa.array(["[1,1,1,1]", "[2,0,1,2]", "[3,2,1,0]", "[4,3,2,1]", "[4,3,2,1]", "[1,2,3,4]", "[1,2,3,4]", "[1,2,3,4]", "[1,2,3,4]", "[1,2,3,4]", "[5,4,3,2]", "[5,4,3,2]", "[5,4,3,2]", "[5,4,3,2]", "[4,3,2,1]", "[6,5,4,3]", "[6,5,4,3]", "[8,7,6,5]", "[9,8,7,6]", "[7,6,5,4]", "[7,6,5,4]", "[7,6,5,4]", "[7,6,5,4]", "[10,11,12,13]", "[11,12,13,14]", "[12,13,14,15]", "[33,44,55,66]", "[22,33,44,55]", "[55,66,77,88]", "[22,33,44,55]"])
], names=["ID", "ListData"])
result_string_groupby = test_table_string.group_by(['ID','ListData']).aggregate([('ListData','count')]).to_pandas()
print("字符串转换后的分组结果:")
print(result_string_groupby)字符串转换后的分组结果:
ID ListData ListData_count 0 a [1,1,1,1] 1 1 a [2,0,1,2] 1 2 a [3,2,1,0] 1 3 a [4,3,2,1] 2 4 b [1,2,3,4] 5 5 c [5,4,3,2] 4 6 c [4,3,2,1] 1 7 d [6,5,4,3] 2 8 d [8,7,6,5] 1 9 d [9,8,7,6] 1 10 e [7,6,5,4] 4 11 e [10,11,12,13] 1 12 f [11,12,13,14] 1 13 f [12,13,14,15] 1 14 f [33,44,55,66] 1 15 f [22,33,44,55] 2 16 f [55,66,77,88] 1
这种方法在功能上能够实现目标,但对于包含大量元素或每个元素本身就很长的列表,将其转换为字符串会带来显著的性能和内存开销。例如,一个包含120个数字,每个数字12字符的列表,转换为字符串后可能长达2.4KB。在大规模数据集上,这种转换可能导致内存溢出或处理速度急剧下降。
为了高效地处理列表类型数据的分组聚合,尤其是在列表长度固定的情况下,我们可以采用“扁平化”策略:将列表中的每个元素提取出来,作为新的独立标量列。这样,group_by操作就可以在这些标量列上执行,而不会遇到类型限制。
使用pyarrow.compute.list_element函数可以按索引提取列表中的单个元素。对于固定长度的列表,我们可以为每个索引创建一个新的列。
# 假设列表长度为4,创建4个新列
columns = {f'c{i}': pc.list_element(test_table_orig['ListData'], i) for i in range(4)}这里,f'c{i}'会生成c0, c1, c2, c3等列名,每个列名对应ListData中特定索引的元素。
将原始的ID列与新创建的标量列组合起来,形成一个新的PyArrow表。
pivot_table = pa.table({'ID': test_table_orig['ID']} | columns)
print("\n扁平化后的表格结构:")
print(pivot_table.schema)
print("\n扁平化后的表格数据(前5行):")
print(pivot_table.slice(0, 5).to_pandas())扁平化后的表格结构:
ID: string c0: int64 c1: int64 c2: int64 c3: int64
扁平化后的表格数据(前5行):
ID c0 c1 c2 c3 0 a 1 1 1 1 1 a 2 0 1 2 2 a 3 2 1 0 3 a 4 3 2 1 4 a 4 3 2 1
现在,pivot_table中的所有列都是标量类型。我们可以使用group_by方法对所有这些列进行分组,并计算每组的行数,从而得到原始列表的频率。
# 对所有列进行分组,并计算每组的行数
counts = pivot_table.group_by(pivot_table.column_names).aggregate([([],'count_all')])
result_list_groupby = counts.to_pandas()
print("\n扁平化后分组聚合结果:")
print(result_list_groupby)扁平化后分组聚合结果:
ID c0 c1 c2 c3 count_all 0 a 1 1 1 1 1 1 a 2 0 1 2 1 2 a 3 2 1 0 1 3 a 4 3 2 1 2 4 b 1 2 3 4 5 5 c 5 4 3 2 4 6 c 4 3 2 1 1 7 d 6 5 4 3 2 8 d 8 7 6 5 1 9 d 9 8 7 6 1 10 e 7 6 5 4 4 11 e 10 11 12 13 1 12 f 11 12 13 14 1 13 f 12 13 14 15 1 14 f 33 44 55 66 1 15 f 22 33 44 55 2 16 f 55 66 77 88 1
这个结果与字符串转换方法得到的结果在逻辑上是等价的,但避免了不必要的字符串转换开销。
pyarrow.compute.list_element(array, index)是一个非常实用的函数,用于从列表类型数组(或列)中提取指定索引位置的元素。
通过循环使用此函数,我们可以将一个列表列“解构”成多个标量列。
在PyArrow中统计列表类型数据的频率,直接使用group_by是不支持的。通过将列表中的每个固定位置的元素提取为独立的标量列,然后对这些新生成的标量列进行分组聚合,可以有效地解决这一问题。这种方法避免了字符串转换带来的性能和内存开销,为处理大规模列表数据提供了一种高效且专业的解决方案。在应用此方法时,需要注意列表长度的固定性,并根据实际数据规模权衡性能与内存。
以上就是PyArrow中列表类型数据的频率统计与聚合的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号