基于Python实现百万级月球陨石坑直径数据集分类与统计
月球陨石坑数据集分类与统计解决方案
核心思路
- 先明确自定义直径区间规则,按从大到小/从小到大的顺序定义,避免匹配逻辑冲突
- 针对80万样本,优先用高效工具处理,同时提供无依赖的纯Python方案
- 读取数据时注意处理空格分隔的格式,同时兼容脏数据(如缺失字段、非数值直径)
- 分类完成后统计各类别数量,可选保存分类结果
方法一:用Pandas高效处理(推荐)
Pandas对结构化数据的处理效率远高于纯Python,适合十万级以上样本:
import pandas as pd # 1. 定义直径区间与对应类别(可根据需求修改) # bins为区间边界,labels为对应类别名,左闭右开规则,include_lowest=True让第一个区间包含最小值 bins = [-float('inf'), 1, 30, 50, float('inf')] labels = ["SET1", "SET2", "SETX", "SET3"] # 2. 读取空格分隔的数据集 # 若无表头则指定header=None,用names定义字段名;sep=r'\s+'匹配任意多个空格分隔符 df = pd.read_csv( "crater_data.txt", sep=r'\s+', header=None, names=["ID", "latitude", "longitude", "diameter", "depth"], dtype={"diameter": float} # 提前指定字段类型,提升效率 ) # 3. 按直径区间分类 df["category"] = pd.cut( df["diameter"], bins=bins, labels=labels, include_lowest=True ) # 4. 统计各类别数量(按类别顺序排序) category_counts = df["category"].value_counts().sort_index() # 输出统计结果 print("各类别陨石坑数量:") print(category_counts) # 可选:保存分类后的数据(空格分隔) df.to_csv("classified_craters.txt", sep=" ", index=False)
内存优化(超大数据集)
若数据集远超内存,用分块读取方式:
chunk_size = 100000 total_counts = pd.Series(dtype='int64') for chunk in pd.read_csv( "crater_data.txt", sep=r'\s+', header=None, names=["ID", "latitude", "longitude", "diameter", "depth"], chunksize=chunk_size ): chunk["category"] = pd.cut(chunk["diameter"], bins=bins, labels=labels, include_lowest=True) chunk_counts = chunk["category"].value_counts() total_counts = total_counts.add(chunk_counts, fill_value=0) print("各类别陨石坑数量:") print(total_counts.sort_index())
方法二:纯Python逐行处理(无依赖)
适合无法安装第三方库的场景,逐行读取避免内存溢出:
# 1. 定义分类逻辑函数 def get_crater_category(diameter_str): try: d = float(diameter_str) except ValueError: return "INVALID" # 标记脏数据 if d < 1: return "SET1" elif 1 <= d <= 30: return "SET2" elif 30 < d < 50: return "SETX" else: return "SET3" # 2. 初始化统计字典 counts = { "SET1": 0, "SET2": 0, "SETX": 0, "SET3": 0, "INVALID": 0 # 统计脏数据数量 } # 3. 逐行读取并处理 with open("crater_data.txt", "r", encoding="utf-8") as f: # 若文件有表头,先跳过第一行:next(f) for line_num, line in enumerate(f, 1): line = line.strip() if not line: continue fields = line.split() # 校验字段数量,跳过异常行 if len(fields) != 5: counts["INVALID"] += 1 continue diameter = fields[3] category = get_crater_category(diameter) counts[category] += 1 # 4. 输出统计结果 print("各类别陨石坑数量:") for category, num in counts.items(): print(f"{category}: {num}")
关键注意事项
- 区间规则顺序:必须按从小到大(或从大到小)的顺序判断,避免大区间先匹配导致逻辑错误
- 脏数据处理:加入异常捕获(如非数值直径、字段缺失),避免程序崩溃并统计异常样本
- 区间边界调整:根据实际需求修改
bins或分类函数的条件,比如是否包含等于30、50的情况
内容的提问来源于stack exchange,提问作者orangecar
相关产品推荐
相关产品推荐

