You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数据预处理中如何跳过连续分隔符?

问题:处理含不规则空格的ASCII数据集时出现NaN值及加载失败问题

背景

我正在清理一个存在不规则空格的ASCII数据集,示例如下:

dataset =
[1 1  1        1  1    1 1  1
1 1 1     1   1     1    4
    2    1    1  1   1  1 1 1]

当前代码可以运行,但因为分隔符设为' ',会把单个空格识别为列分隔,导致提取的features出现大量NaN值:

features = [ nan nan nan nan 2
                   2 nan nan nan 1 nan
                   nan nan nan 3 nan]

现有代码

import pandas as pd
import torch
from torch.utils.data import Dataset, DataLoader, random_split
import numpy as np
import os

class SDataset(Dataset):
    def __init__(self, directory, delimiter=' '):
        self.data = []
        self.labels = []
        self.delimiter = delimiter

        # 遍历目录下所有文件
        for filename in os.listdir(directory):
            if filename.endswith('.f16'):
                file_path = os.path.join(directory, filename)
                try:
                    # 加载ASCII数据
                    df = pd.read_csv(file_path, delimiter=self.delimiter, header=None, engine='python')
                    # 确保列数足够
                    if df.shape[1] >= 21:
                        # 提取特征和标签
                        features = df.iloc[:, [12, 13]].values
                        labels = df.iloc[:, 6].values  
                        self.data.append(features)
                        self.labels.append(labels)
                    else:
                        print(f"文件 {filename} 列数不足。")
                except Exception as e:
                    print(f"加载文件 {filename} 出错: {e}")

        if not self.data:
            raise ValueError("未找到有效数据。")

        # 堆叠特征
        self.data = np.vstack(self.data)  
        # 拼接标签
        self.labels = np.concatenate(self.labels)  

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, idx):
        features = torch.tensor(self.data[idx], dtype=torch.float32)
        label = torch.tensor(self.labels[idx], dtype=torch.float32)
        return features, label

# 加载目录下的.f16文件数据集
dataset_directory = "C:/.../.../.../.../..."
dataset = SDataset(dataset_directory, delimiter=' ')

# 定义拆分比例
train_size = int(0.7 * len(dataset))  # 70% 用于训练
test_size = len(dataset) - train_size  # 剩余用于测试

# 拆分数据集
train_dataset, test_dataset = random_split(dataset, [train_size, test_size])

# 创建DataLoader
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

# 训练循环
for batch_idx, (features, labels) in enumerate(train_loader):
    print(f"训练批次 {batch_idx+1}")
    print("特征:", features)
    print("标签:", labels)

# 测试循环
for batch_idx, (features, labels) in enumerate(test_loader):
    print(f"测试批次 {batch_idx+1}")
    print("特征:", features)
    print("标签:", labels)

尝试的解决方法及报错

我尝试添加.strip()方法来移除空格,修改后的代码片段如下:

try:
    # 加载ASCII数据
    df = pd.read_csv(file_path, delimiter=self.delimiter, header=None, engine='python')
    # 确保列数足够
    if df.shape[1] >= 21:
        # 提取特征和标签
        df = df.strip()
        features = df.iloc[:, [12, 13]].values
        labels = df.iloc[:, 6].values  
        self.data.append(features)
        self.labels.append(labels)
    else:
        print(f"文件 {filename} 列数不足。")

但运行后出现以下错误:

Traceback (most recent call last):
  File "c:---.py", line 51, in <module>
    dataset = SDataset(dataset_directory, delimiter=' ')
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:---.py", line 34, in __init__
    raise ValueError("No valid data found. Ensure files contain the correct number of columns.")
ValueError: No valid data found. Ensure files contain the correct number of columns.

解决方案

问题出在两个核心点:

  1. 单个空格作为分隔符时,pd.read_csv会将连续空格拆分为多个分隔符,生成大量空列,最终导致NaN值。
  2. df.strip()是错误用法——DataFrame对象没有该方法,这会直接抛出异常,导致所有文件加载失败,触发No valid data found错误。

正确处理方式:

方法一:使用正则表达式作为分隔符

将分隔符设置为匹配任意数量的空白字符(空格、制表符等),即delimiter=r'\s+',这样pd.read_csv会自动将连续多个空格视为单个分隔符,不会生成空列。

修改读取数据的代码:

df = pd.read_csv(file_path, delimiter=r'\s+', header=None, engine='python')

注:必须指定engine='python',默认的c引擎不支持正则表达式分隔符。

方法二:先清理文件内容再加载

如果正则分隔符不生效,可以先读取文件内容,将每行的连续空格替换为单个空格,再用StringIO加载为DataFrame:

import io

with open(file_path, 'r') as f:
    content = f.read()
# 替换连续空格为单个空格,同时过滤空行
cleaned_content = '\n'.join([' '.join(line.split()) for line in content.splitlines() if line.strip()])
df = pd.read_csv(io.StringIO(cleaned_content), delimiter=' ', header=None)

移除错误的df.strip()调用

直接删除df = df.strip()这一行。若需要清理单元格内的空格,可使用df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x),但在本场景下,使用正则分隔符后无需额外清理。

修改后的SDataset类初始化关键代码:

try:
    # 使用正则分隔符处理连续空格
    df = pd.read_csv(file_path, delimiter=r'\s+', header=None, engine='python')
    # 确保列数足够
    if df.shape[1] >= 21:
        # 提取特征和标签
        features = df.iloc[:, [12, 13]].values
        labels = df.iloc[:, 6].values  
        self.data.append(features)
        self.labels.append(labels)
    else:
        print(f"文件 {filename} 列数不足。")
except Exception as e:
    print(f"加载文件 {filename} 出错: {e}")

这样就能正确加载数据,避免NaN值和加载失败的问题。


内容的提问来源于stack exchange,提问作者Daedalus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:19:51