Skip to content

Commit 370c691

Browse files
yigitee-org
authored andcommitted
0.1.9
Signed-off-by: yi <[email protected]>
1 parent 970717e commit 370c691

File tree

7 files changed

+630
-0
lines changed

7 files changed

+630
-0
lines changed

myz_tools/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import *
206 Bytes
Binary file not shown.
Binary file not shown.
454 Bytes
Binary file not shown.

myz_tools/all_test.py

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import os
2+
import shutil
3+
import unittest
4+
5+
import numpy as np
6+
import pandas as pd
7+
from common_maths import *
8+
9+
10+
#################################################################################
11+
class TestCreateDir(unittest.TestCase):
12+
"""TestCreateDir"""
13+
14+
def setUp(self):
15+
"""在每个测试之前运行的代码,用于设置测试环境"""
16+
self.test_dir = "test_create_dir"
17+
self.sub_dir = "subfolder"
18+
self.test_path = os.path.join(self.test_dir, self.sub_dir)
19+
20+
# 确保测试目录是干净的
21+
if os.path.exists(self.test_dir):
22+
shutil.rmtree(self.test_dir)
23+
os.makedirs(self.test_dir)
24+
25+
def tearDown(self):
26+
"""在每个测试之后运行的代码,用于清理测试环境"""
27+
if os.path.exists(self.test_dir):
28+
shutil.rmtree(self.test_dir)
29+
30+
def test_create_new_directory(self):
31+
"""测试函数在不存在的路径中创建目录"""
32+
new_dir_name = "new_folder"
33+
create_dir(new_dir_name, self.test_dir)
34+
full_path = os.path.join(self.test_dir, new_dir_name)
35+
self.assertTrue(os.path.exists(full_path), "目录未创建成功")
36+
37+
def test_directory_already_exists(self):
38+
"""测试函数在目录已经存在的情况下处理"""
39+
existing_dir_name = "existing_folder"
40+
os.makedirs(os.path.join(self.test_dir, existing_dir_name))
41+
create_dir(existing_dir_name, self.test_dir)
42+
# 验证目录是否仍然存在,且没有抛出异常
43+
full_path = os.path.join(self.test_dir, existing_dir_name)
44+
self.assertTrue(os.path.exists(full_path), "目录应该已经存在")
45+
46+
47+
#######################################################################
48+
49+
50+
class TestGetMaxDiff(unittest.TestCase):
51+
def test_standard_case(self):
52+
"""测试函数在正常二维数组中的行为"""
53+
array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
54+
expected = np.array([6, 6, 6]) # 每列的最大值与最小值的差
55+
result = get_max_diff(array)
56+
np.testing.assert_array_equal(result, expected)
57+
58+
# def test_empty_array(self):
59+
# """测试函数在空二维数组中的行为"""
60+
# array = []
61+
# expected = np.array([])
62+
# result = get_max_diff(array)
63+
# np.testing.assert_array_equal(result, expected)
64+
65+
def test_single_column_array(self):
66+
"""测试函数在只有一列的二维数组中的行为"""
67+
array = [[1], [3], [5]]
68+
expected = np.array([4]) # 只有一列,最大值与最小值的差
69+
result = get_max_diff(array)
70+
np.testing.assert_array_equal(result, expected)
71+
72+
def test_invalid_input(self):
73+
"""测试函数在非二维数组输入中的行为"""
74+
with self.assertRaises(ValueError):
75+
get_max_diff([1, 2, 3]) # 一维数组
76+
77+
with self.assertRaises(ValueError):
78+
get_max_diff([[1, 2], [3, 4], [5]]) # 不规则的二维数组
79+
80+
def test_non_numeric_data(self):
81+
"""测试函数在包含非数字数据的二维数组中的行为"""
82+
array = [[1, 2, "a"], [3, 4, "b"]]
83+
with self.assertRaises(TypeError):
84+
get_max_diff(array)
85+
86+
87+
###########################################################################################
88+
class TestRemoveOutliersIQR(unittest.TestCase):
89+
def test_remove_outliers_basic(self):
90+
"""
91+
测试简单的二维数组,确保函数能正确去除异常值。
92+
"""
93+
data = np.array(
94+
[
95+
[1, 2, 3, 4],
96+
[5, 5, 5, 5],
97+
[100, 200, 300, 1000], # 明显的异常值
98+
[2, 3, 4, 5],
99+
[6, 7, 8, 9],
100+
[0, 0, 0, 0],
101+
]
102+
)
103+
104+
cleaned_data, valid_indices = remove_outliers_iqr(data)
105+
expected_data = np.array(
106+
[[1, 2, 3, 4], [5, 5, 5, 5], [2, 3, 4, 5], [6, 7, 8, 9], [0, 0, 0, 0]]
107+
)
108+
109+
expected_indices = [0, 1, 3, 4, 5]
110+
111+
np.testing.assert_array_equal(cleaned_data, expected_data)
112+
np.testing.assert_array_equal(valid_indices, expected_indices)
113+
114+
def test_all_inliers(self):
115+
"""
116+
测试当没有异常值时,所有数据都应该保留。
117+
"""
118+
data = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [2, 3, 4, 5], [6, 7, 8, 9]])
119+
120+
cleaned_data, valid_indices = remove_outliers_iqr(data)
121+
122+
np.testing.assert_array_equal(cleaned_data, data)
123+
np.testing.assert_array_equal(valid_indices, [0, 1, 2, 3])
124+
125+
def test_single_column(self):
126+
"""
127+
测试只有一列数据的情况。
128+
"""
129+
data = np.array([[1], [2], [100], [3], [4]]) # 异常值
130+
131+
cleaned_data, valid_indices = remove_outliers_iqr(data)
132+
expected_data = np.array([[1], [2], [3], [4]])
133+
134+
expected_indices = [0, 1, 3, 4]
135+
136+
np.testing.assert_array_equal(cleaned_data, expected_data)
137+
np.testing.assert_array_equal(valid_indices, expected_indices)
138+
139+
140+
##################################################################
141+
class TestExportToCsv(unittest.TestCase):
142+
def setUp(self):
143+
"""在每个测试之前运行的代码,用于设置测试环境"""
144+
self.test_dir = "test_output"
145+
self.test_file = "test_data"
146+
self.test_data = [[1, 2, 3], [4, 5, 6]]
147+
148+
# 确保测试目录是干净的
149+
if os.path.exists(self.test_dir):
150+
shutil.rmtree(self.test_dir)
151+
os.makedirs(self.test_dir)
152+
153+
def tearDown(self):
154+
"""在每个测试之后运行的代码,用于清理测试环境"""
155+
if os.path.exists(self.test_dir):
156+
shutil.rmtree(self.test_dir)
157+
158+
def test_file_creation(self):
159+
"""测试函数是否能够创建CSV文件"""
160+
export_to_csv(self.test_data, self.test_file, self.test_dir)
161+
file_path = os.path.join(self.test_dir, self.test_file + ".csv")
162+
self.assertTrue(os.path.exists(file_path), "CSV文件未创建成功")
163+
164+
def test_data_written_correctly(self):
165+
"""测试函数是否正确写入数据到CSV文件"""
166+
export_to_csv(self.test_data, self.test_file, self.test_dir)
167+
168+
file_path = os.path.join(self.test_dir, self.test_file + ".csv")
169+
# 检查CSV内容是否正确
170+
df = pd.read_csv(file_path, header=None, index_col=False)
171+
self.assertTrue(df.equals(pd.DataFrame(self.test_data)), "CSV文件内容不匹配")
172+
173+
def test_append_data(self):
174+
"""测试函数在文件存在时是否能够正确追加数据"""
175+
export_to_csv(self.test_data, self.test_file, self.test_dir)
176+
additional_data = [[7, 8, 9]]
177+
export_to_csv(additional_data, self.test_file, self.test_dir)
178+
179+
file_path = os.path.join(self.test_dir, self.test_file + ".csv")
180+
181+
# 检查CSV内容是否包含追加的数据
182+
df = pd.read_csv(file_path, header=None, index_col=False)
183+
expected_data = self.test_data + additional_data
184+
self.assertTrue(df.equals(pd.DataFrame(expected_data)), "数据追加失败")
185+
186+
# def test_empty_data(self):
187+
# """测试函数在传入空数据时的处理"""
188+
# try:
189+
# export_to_csv([], self.test_file, self.test_dir)
190+
# except Exception as e:
191+
# self.fail(f"函数在处理空数据时抛出异常: {e}")
192+
193+
# file_path = os.path.join(self.test_dir, self.test_file + ".csv")
194+
195+
# self.assertTrue(os.path.exists(file_path), "CSV文件未创建")
196+
197+
# # 检查CSV文件内容
198+
# df = pd.read_csv(file_path)
199+
# self.assertTrue(df.empty, "CSV文件不应包含数据")
200+
201+
202+
if __name__ == "__main__":
203+
unittest.main()

myz_tools/common_maths.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import os
2+
3+
import numpy as np
4+
import pandas as pd
5+
6+
7+
# 单元测试通过
8+
def create_dir(dir_name, path="."):
9+
"""
10+
在指定路径下创建名称为{dir_name}的文件夹
11+
Args:
12+
dir_name: 文件夹名称
13+
path: 要创建文件夹的路径,默认为当前路径
14+
15+
Returns:
16+
17+
"""
18+
full_path = os.path.join(path, dir_name)
19+
try:
20+
if not os.path.exists(full_path):
21+
os.makedirs(full_path)
22+
print(f"文件夹 '{dir_name}' 已成功创建于 {path}")
23+
else:
24+
print(f"文件夹 '{dir_name}' 已经存在于 {path}")
25+
except OSError as e:
26+
print(f"创建文件夹 '{dir_name}' 失败: {e}")
27+
28+
29+
# 单元测试通过
30+
def get_max_diff(two_dimensional_array):
31+
"""
32+
参数:
33+
two_dimensional_array: 二维数组
34+
返回值:
35+
每一列里面最大值和最小值的差值,类型是一个一维数组
36+
功能:
37+
传入一个二维数组,函数返回每一列里面最大值和最小值的差值。
38+
"""
39+
# 将输入转换为 NumPy 数组,并确保其为二维数组
40+
data = np.asarray(two_dimensional_array)
41+
42+
if data.ndim != 2:
43+
raise ValueError("输入必须是一个二维数组或可以转换为二维数组的结构")
44+
45+
# 使用 NumPy 的 ptp 函数直接计算每列的最大值和最小值差值
46+
diff = np.ptp(data, axis=0)
47+
48+
return diff
49+
50+
51+
# 单元测试通过
52+
def remove_outliers_iqr(data):
53+
"""
54+
参数:
55+
data: 二维数组
56+
返回值:
57+
去除异常值后的二维数组和有效的行索引,类型是一个元组
58+
功能:
59+
四分位距法去除传入的二维数组中的异常值,注意是对于每一列来说的自己的异常值
60+
"""
61+
data = np.asarray(data)
62+
63+
# 记录哪些行满足条件
64+
valid_rows = np.ones(data.shape[0], dtype=bool)
65+
66+
for col in range(data.shape[1]):
67+
# 计算Q1和Q3
68+
Q1 = np.percentile(data[:, col], 25)
69+
Q3 = np.percentile(data[:, col], 75)
70+
IQR = Q3 - Q1
71+
72+
# 计算上下边界
73+
lower_bound = Q1 - 1.5 * IQR
74+
upper_bound = Q3 + 1.5 * IQR
75+
76+
# 更新valid_rows数组,保留不包含异常值的行
77+
valid_rows &= (data[:, col] >= lower_bound) & (data[:, col] <= upper_bound)
78+
79+
# 筛选出有效的行
80+
cleaned_data = data[valid_rows]
81+
82+
# 返回去除异常值后的数组和行索引
83+
valid_indices = np.where(valid_rows)[0]
84+
85+
return cleaned_data, valid_indices
86+
87+
88+
# 单元测试通过
89+
def export_to_csv(array_data, file_name, output_directory="."):
90+
"""
91+
参数:
92+
array_data: 二维数组,要保存的数据
93+
file_name: 字符串,CSV文件的名称(不包含扩展名)
94+
output_directory: 字符串,保存文件的目录路径,默认为当前目录
95+
返回:
96+
None
97+
功能:
98+
将给定的二维数组保存到指定目录中的CSV文件。如果文件已存在,则追加数据,并在每次写入时添加空行作为分隔符。
99+
"""
100+
try:
101+
array_data = np.asarray(array_data)
102+
# 确保输入的是二维数组
103+
if array_data.ndim != 2:
104+
raise ValueError("输入必须是一个二维数组或可以转换为二维数组的结构")
105+
# 确保输出目录存在
106+
os.makedirs(output_directory, exist_ok=True)
107+
108+
# 构建完整的文件路径
109+
full_file_path = os.path.join(output_directory, file_name + ".csv")
110+
111+
# 判断文件是否存在并设置写入模式
112+
write_mode = "a" if os.path.exists(full_file_path) else "w"
113+
114+
# 将二维数组转换为DataFrame并保存为CSV文件
115+
df = pd.DataFrame(array_data)
116+
df.to_csv(full_file_path, mode=write_mode, index=False, header=False)
117+
118+
# 在文件末尾添加空行以分隔数据块
119+
with open(full_file_path, "a", encoding="utf-8") as file:
120+
file.write("\n")
121+
122+
except Exception as error:
123+
raise IOError(f"保存数据到CSV文件失败: {str(error)}")
124+
125+
126+
if __name__ == "__main__":
127+
pass

0 commit comments

Comments
 (0)