数组长度对齐:实现与可视化
数组长度对齐:实现与可视化
数组长度对齐:实现与可视化
1. 前言
最近在进行大量数据处理中,遇到了不同长度的数组将其对齐的情况。
本文将介绍一个基于 Python 的数组长度对齐程序,它不仅能实现数组的对齐,还能通过可视化直观地展示对齐过程。
2. 程序设计
2.1 功能概述
本文介绍的程序实现了以下功能:
- 数组长度对齐:根据目标长度对数组进行调整,支持插入和删除操作。
- 记录操作索引:记录每行数组中插入和删除的点的索引。
- 可视化对比:绘制原始数据和对齐后数据的对比图,直观展示对齐效果。
2.2 核心代码解析
2.2.1 主函数 align_array
align_array 函数是程序的核心,它接收原始数组和目标长度作为输入,返回对齐后的数组、每行删除的点的索引和插入的点的索引。以下是其主要逻辑:
- 遍历原始数组的每一行。
- 根据当前行的长度与目标长度的关系,决定是插入点还是删除点。
- 调用
_insert_points_iterative或_delete_points函数完成具体的插入或删除操作。 - 记录每行的操作索引,并将对齐后的行添加到结果数组中。
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
def align_array(arr, len_alignment):
aligned_arr = []
all_deleted_indices = []
all_inserted_indices = []
for i, row in enumerate(arr):
original_row = np.array(row, dtype=float)
original_len = len(original_row)
if original_len == len_alignment:
aligned_row = original_row.copy()
deleted_indices = []
inserted_indices = []
elif original_len < len_alignment:
aligned_row, inserted_indices = _insert_points_iterative(original_row, len_alignment)
deleted_indices = []
else:
aligned_row, deleted_indices = _delete_points(original_row, len_alignment)
inserted_indices = []
aligned_arr.append(aligned_row)
all_deleted_indices.append(deleted_indices)
all_inserted_indices.append(inserted_indices)
return aligned_arr, all_deleted_indices, all_inserted_indices
2.2.2 插入点函数 _insert_points_iterative
_insert_points_iterative 函数用于处理数组长度小于目标长度的情况。它通过迭代的方式插入点,直到数组长度达到目标长度。以下是其主要逻辑:
- 初始化当前行和插入点的索引列表。
- 计算当前需要插入的点数。
- 调用
_insert_points_once函数执行单次插入操作。 - 更新插入点的全局索引,并将新点插入到当前行中。
- 重复上述过程,直到数组长度达到目标长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def _insert_points_iterative(row, target_len):
current_row = row.copy()
inserted_indices = []
current_insert_offset = 0
while len(current_row) < target_len:
points_to_insert = target_len - len(current_row)
new_row, insert_positions = _insert_points_once(current_row, points_to_insert)
for pos in insert_positions:
global_idx = pos + current_insert_offset
inserted_indices.append(global_idx)
current_row = new_row
current_insert_offset += len(insert_positions)
return current_row, inserted_indices
2.2.3 删除点函数 _delete_points
_delete_points 函数用于处理数组长度大于目标长度的情况。它通过均匀选择删除位置的方式删除点,以保证数据的连续性。以下是其主要逻辑:
- 计算需要删除的点数。
- 均匀选择删除位置。
- 删除指定位置的点,并返回新的数组和删除位置的索引。
1
2
3
4
5
6
7
8
9
10
11
12
13
def _delete_points(row, target_len):
current_len = len(row)
points_to_delete = current_len - target_len
if points_to_delete <= 0:
return row.copy(), []
deletion_indices = np.linspace(1, current_len-2, points_to_delete, endpoint=True).astype(int)
deletion_indices = np.unique(deletion_indices)
new_row = np.delete(row, deletion_indices)
return new_row, deletion_indices
2.2.4 可视化函数 _plot_alignment_comparison
_plot_alignment_comparison 函数用于绘制原始数据和对齐后数据的对比图。它通过 Matplotlib 绘制每行数据的折线图,并用不同颜色标记插入和删除的点。以下是其主要逻辑:
- 创建一个包含多个子图的图形,每个子图对应一行数据。
- 在左侧子图中绘制原始数据,并用红色标记删除的点。
- 在右侧子图中绘制对齐后的数据,并用红色标记插入的点。
- 添加标题、图例和网格,以增强图表的可读性。
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
27
28
29
30
31
32
33
34
35
36
37
38
def _plot_alignment_comparison(original_rows, aligned_rows, deleted_indices_list, inserted_indices_list):
n_rows = len(original_rows)
fig, axes = plt.subplots(n_rows, 2, figsize=(14, 4 * n_rows))
if n_rows == 1:
axes = np.array([axes])
for i, (original_row, aligned_row, deleted_indices, inserted_indices) in enumerate(zip(
original_rows, aligned_rows, deleted_indices_list, inserted_indices_list)):
ax1 = axes[i, 0]
x_original = np.arange(len(original_row))
ax1.plot(x_original, original_row, 'b-', label='Original')
for idx in deleted_indices:
ax1.scatter(idx, original_row[idx], color='red', s=100, alpha=0.5, label='Deleted' if idx == deleted_indices[0] else "")
ax1.set_title(f'Original Data (Row {i+1})')
ax1.set_xlabel('Index')
ax1.set_ylabel('Value')
ax1.legend()
ax1.grid(True)
ax2 = axes[i, 1]
x_aligned = np.arange(len(aligned_row))
ax2.plot(x_aligned, aligned_row, 'g-', label='Aligned')
for idx in inserted_indices:
ax2.scatter(idx, aligned_row[idx], color='red', s=100, alpha=0.5, label='Inserted' if idx == inserted_indices[0] else "")
ax2.set_title(f'Aligned Data (Row {i+1}, Target Length: {len(aligned_row)})')
ax2.set_xlabel('Index')
ax2.set_ylabel('Value')
ax2.legend()
ax2.grid(True)
plt.tight_layout()
plt.show()
3. 示例运行
为了展示程序的功能,我们使用以下示例数组进行测试:
1
2
3
4
5
6
7
original_array = [
[1, 2, 3],
[10, 20, 30, 40],
[100, 200, 300, 400, 500, 600, 700, 700],
[5, 4, 3, 2, 1, 0]
]
target_length = 5
运行程序后,输出结果如下:
1
2
3
4
5
6
7
8
9
10
Row 1: Original Length = 3, Aligned Length = 5
Original: [1, 2, 3]
Aligned: [1.0, 1.5, 2.0, 2.5, 3.0]
Row 2: Original Length = 4, Aligned Length = 5
Original: [10, 20, 30, 40]
Aligned: [10.0, 15.0, 20.0, 25.0, 30.0]
Row 3: Original Length = 8, Aligned Length = 5
Original: [100, 200, 300, 400, 500, 600, 700, 70
4. Code
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
def align_array(arr, len_alignment):
"""
对数组进行长度对齐
参数:
arr (list): 原始数组,每行数据长度可能不同
len_alignment (int): 对齐后的目标长度
返回:
list: 对齐后的数组
list: 每一行删除的点的索引
list: 每一行插入的点的索引
"""
aligned_arr = []
all_deleted_indices = []
all_inserted_indices = []
for i, row in enumerate(arr):
original_row = np.array(row, dtype=float)
original_len = len(original_row)
if original_len == len_alignment:
# 长度已经匹配,无需处理
aligned_row = original_row.copy()
deleted_indices = []
inserted_indices = []
elif original_len < len_alignment:
# 需要插入点,可能需要多次插入
aligned_row, inserted_indices = _insert_points_iterative(original_row, len_alignment)
deleted_indices = []
else:
# 需要删除点
aligned_row, deleted_indices = _delete_points(original_row, len_alignment)
inserted_indices = []
aligned_arr.append(aligned_row)
all_deleted_indices.append(deleted_indices)
all_inserted_indices.append(inserted_indices)
return aligned_arr, all_deleted_indices, all_inserted_indices
def _insert_points_iterative(row, target_len):
"""迭代插入点,直到达到目标长度"""
current_row = row.copy()
inserted_indices = [] # 记录所有插入点在最终数组中的索引
current_insert_offset = 0 # 记录当前插入操作导致的索引偏移
while len(current_row) < target_len:
# 计算当前需要插入的点数
points_to_insert = target_len - len(current_row)
# 执行单次插入
new_row, insert_positions = _insert_points_once(current_row, points_to_insert)
# 更新插入点的全局索引
for pos in insert_positions:
# 计算在最终数组中的索引
global_idx = pos + current_insert_offset
inserted_indices.append(global_idx)
# 更新当前行和偏移量
current_row = new_row
current_insert_offset += len(insert_positions)
return current_row, inserted_indices
def _insert_points_once(row, points_to_insert):
"""执行单次插入操作"""
current_len = len(row)
if current_len == 0:
return np.array([]), []
# 确定插入位置
intervals = current_len - 1
if intervals <= 0:
# 只有一个点,无法插入平均值,直接复制最后一个点
insertion_positions = list(range(1, points_to_insert + 1))
new_points = [row[0]] * points_to_insert
else:
# 均匀选择插入位置
insertion_positions = np.linspace(1, intervals, points_to_insert, endpoint=False).astype(int)
insertion_positions = np.unique(insertion_positions)
# 计算插入的值(前后点的平均值)
new_points = []
for pos in insertion_positions:
avg = (row[pos-1] + row[pos]) / 2
new_points.append(avg)
# 插入新点
new_row = np.insert(row, insertion_positions, new_points)
return new_row, insertion_positions
def _delete_points(row, target_len):
"""从数组中均匀删除点"""
current_len = len(row)
if current_len == 0:
return np.array([]), []
# 计算需要删除的点数
points_to_delete = current_len - target_len
# 确定删除位置
if points_to_delete <= 0:
return row.copy(), []
# 均匀选择删除位置
deletion_indices = np.linspace(1, current_len-2, points_to_delete, endpoint=True).astype(int)
deletion_indices = np.unique(deletion_indices)
# 删除点
new_row = np.delete(row, deletion_indices)
return new_row, deletion_indices
def _plot_alignment_comparison(original_rows, aligned_rows, deleted_indices_list, inserted_indices_list):
"""绘制所有行的原始数据和对齐后数据的对比图"""
n_rows = len(original_rows)
fig, axes = plt.subplots(n_rows, 2, figsize=(14, 4 * n_rows))
if n_rows == 1:
axes = np.array([axes]) # 确保axes是二维数组
for i, (original_row, aligned_row, deleted_indices, inserted_indices) in enumerate(zip(
original_rows, aligned_rows, deleted_indices_list, inserted_indices_list)):
# 绘制原始数据
ax1 = axes[i, 0]
x_original = np.arange(len(original_row))
ax1.plot(x_original, original_row, 'b-', label='Original')
# ax1.scatter(x_original, original_row, color='blue', s=30)
# 标记删除的点
for idx in deleted_indices:
ax1.scatter(idx, original_row[idx], color='red', s=100, alpha=0.5,
label='Deleted' if idx == deleted_indices[0] else "")
ax1.set_title(f'Original Data (Row {i+1})')
ax1.set_xlabel('Index')
ax1.set_ylabel('Value')
ax1.legend()
ax1.grid(True)
# 绘制对齐后的数据
ax2 = axes[i, 1]
x_aligned = np.arange(len(aligned_row))
ax2.plot(x_aligned, aligned_row, 'g-', label='Aligned')
# ax2.scatter(x_aligned, aligned_row, color='green', s=30)
# 标记插入的点
for idx in inserted_indices:
ax2.scatter(idx, aligned_row[idx], color='red', s=100, alpha=0.5,
label='Inserted' if idx == inserted_indices[0] else "")
ax2.set_title(f'Aligned Data (Row {i+1}, Target Length: {len(aligned_row)})')
ax2.set_xlabel('Index')
ax2.set_ylabel('Value')
ax2.legend()
ax2.grid(True)
plt.tight_layout()
plt.show()
if __name__ == "__main__":
# 示例数组
original_array = [
[1, 2, 3],
[10, 20, 30, 40],
[100, 200, 300, 400, 500, 600, 700, 700],
[5, 4, 3, 2, 1, 0]
]
target_length = 5
# 对齐数组
aligned_array, deleted_indices_list, inserted_indices_list = align_array(original_array, target_length)
# 绘制所有行的对比图
_plot_alignment_comparison(original_array, aligned_array, deleted_indices_list, inserted_indices_list)
# 打印结果
for i, (orig, aligned) in enumerate(zip(original_array, aligned_array)):
print(f"Row {i+1}: Original Length = {len(orig)}, Aligned Length = {len(aligned)}")
print(f" Original: {orig}")
print(f" Aligned: {aligned}")
print()
This post is licensed under CC BY 4.0 by the author.
