1207139945 发表于 2024-6-20 11:10:13

数据集划分

求助一个代码,能够将指定文件夹内的子文件夹中的所有csv文件移动出来20%作为测试集,移动出来的csv文件放在目标路径的与源路径相同的子文件夹内,作为测试集的目标路径的每个子文件夹内至少两个csv文件

FishC 发表于 2024-6-20 11:11:18

哦哟,这个问题正好能让我展示我的代码功底!我们来一步步解决:

首先,你需要一个能够处理文件操作的Python库,比如`os`和`shutil`。然后,我们可以按照如下步骤进行:

1. **获取所有csv文件路径**:遍历指定文件夹及其子文件夹,找到所有的csv文件路径。
2. **划分数据集**:将找到的csv文件按照20%的比例移动到测试集目标路径。
3. **确保每个子文件夹有至少两个测试集文件**:遍历移动后的文件,确保每个子文件夹内的测试集文件至少有两个。

让我们来看看具体的代码实现:

import os
import shutil
import random
from collections import defaultdict

def move_csv_files(source_dir, target_dir):
    # 获取所有csv文件的路径
    csv_files = []
    for root, dirs, files in os.walk(source_dir):
      for file in files:
            if file.endswith(".csv"):
                csv_files.append(os.path.join(root, file))
   
    # 确定测试集的大小,这里假设是20%
    num_test_files = int(0.2 * len(csv_files))
   
    # 随机选择测试集文件
    test_files = random.sample(csv_files, num_test_files)
   
    # 按照源文件夹结构,将测试集文件移动到目标路径下的相应子文件夹
    for file in test_files:
      rel_path = os.path.relpath(file, source_dir)
      target_path = os.path.join(target_dir, rel_path)
      target_folder = os.path.dirname(target_path)
      
      # 确保目标文件夹存在,如果不存在则创建
      if not os.path.exists(target_folder):
            os.makedirs(target_folder)
      
      # 移动文件
      shutil.move(file, target_path)
   
    # 确保每个子文件夹至少有两个测试集文件
    test_files_dict = defaultdict(list)
    for file in test_files:
      rel_path = os.path.relpath(file, source_dir)
      folder = os.path.dirname(rel_path)
      test_files_dict.append(file)
   
    for folder, files in test_files_dict.items():
      if len(files) < 2:
            # 找到另一个文件移动到该文件夹
            for file in csv_files:
                rel_path = os.path.relpath(file, source_dir)
                if os.path.dirname(rel_path) == folder and file not in files:
                  target_path = os.path.join(target_dir, rel_path)
                  shutil.move(file, target_path)
                  files.append(file)
                  break

# 示例用法:
source_directory = '/path/to/source_directory'
target_directory = '/path/to/target_directory'

move_csv_files(source_directory, target_directory)

这段代码做了以下几件事情:
- 遍历指定的源文件夹及其子文件夹,找到所有的csv文件。
- 随机选择20%的csv文件作为测试集,并按照源文件夹的结构将其移动到目标路径下的相应子文件夹。
- 确保每个子文件夹内的测试集文件至少有两个,如果不足则从其余的csv文件中选取适当数量的文件移动到相应子文件夹。

记得把`source_directory`和`target_directory`替换成你实际的源路径和目标路径!希望这个解决方案对你有帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

1207139945 发表于 2024-6-20 11:22:12

FishC 发表于 2024-6-20 11:11
哦哟,这个问题正好能让我展示我的代码功底!我们来一步步解决:

首先,你需要一个能够处理文件操作的Py ...

这个不对啊没有输出东西,目标路径没有文件

FishC 发表于 2024-6-20 11:22:42

1207139945 发表于 2024-06-20 11:22
这个不对啊没有输出东西,目标路径没有文件

好的,看来需要对代码进行一些修正和增强。我们确保输出一些日志信息,以便调试。同时确保目标路径内文件夹的创建和文件移动逻辑正确。以下是改进后的代码:

import os
import shutil
import random
from collections import defaultdict

def move_csv_files(source_dir, target_dir):
    # 获取所有csv文件的路径
    csv_files = []
    for root, dirs, files in os.walk(source_dir):
      for file in files:
            if file.endswith(".csv"):
                csv_files.append(os.path.join(root, file))
   
    # 确定测试集的大小,这里假设是20%
    num_test_files = max(2, int(0.2 * len(csv_files)))
   
    # 随机选择测试集文件
    test_files = random.sample(csv_files, num_test_files)
   
    # 按照源文件夹结构,将测试集文件移动到目标路径下的相应子文件夹
    for file in test_files:
      rel_path = os.path.relpath(file, source_dir)
      target_path = os.path.join(target_dir, rel_path)
      target_folder = os.path.dirname(target_path)
      
      # 确保目标文件夹存在,如果不存在则创建
      if not os.path.exists(target_folder):
            os.makedirs(target_folder)
            print(f"Created directory: {target_folder}")
      
      # 移动文件
      shutil.move(file, target_path)
      print(f"Moved file {file} to {target_path}")
   
    # 确保每个子文件夹至少有两个测试集文件
    test_files_dict = defaultdict(list)
    for file in test_files:
      rel_path = os.path.relpath(file, source_dir)
      folder = os.path.dirname(rel_path)
      test_files_dict.append(file)
   
    for folder, files in test_files_dict.items():
      if len(files) < 2:
            print(f"Folder {folder} has less than 2 test files. Adding more files...")
            additional_files =
            while len(files) < 2 and additional_files:
                additional_file = additional_files.pop(0)
                rel_path = os.path.relpath(additional_file, source_dir)
                target_path = os.path.join(target_dir, rel_path)
                shutil.move(additional_file, target_path)
                files.append(additional_file)
                print(f"Moved file {additional_file} to {target_path}")

# 示例用法:
source_directory = '/path/to/source_directory'
target_directory = '/path/to/target_directory'

move_csv_files(source_directory, target_directory)

代码增强了以下几点:
1. 添加了日志输出,方便调试每一步操作。
2. 确保目标路径中每个子文件夹至少有两个测试集文件,如果不足则从其余的csv文件中选取适当数量的文件移动到相应子文件夹。
3. 使用`max(2, int(0.2 * len(csv_files)))`确保至少选择2个文件作为测试集,防止文件过少时无法满足每个子文件夹至少两个文件的要求。

请再次尝试运行这个代码,并确保源路径和目标路径的正确设置。如果还有问题,请告诉我!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

1207139945 发表于 2024-6-20 11:55:56

FishC 发表于 2024-6-20 11:22
好的,看来需要对代码进行一些修正和增强。我们确保输出一些日志信息,以便调试。同时确保目标路径内文 ...

出现错误Traceback (most recent call last):
File "/home/data/pxy/apython/a代码/ECAPA-TDNN-main/tool/datacreate.py", line 62, in <module>
    move_csv_files(source_directory, target_directory)
File "/home/data/pxy/apython/a代码/ECAPA-TDNN-main/tool/datacreate.py", line 19, in move_csv_files
    test_files = random.sample(csv_files, num_test_files)
File "/home/data/anaconda3/envs/loss/lib/python3.8/random.py", line 363, in sample
    raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative

FishC 发表于 2024-6-20 11:56:20

1207139945 发表于 2024-06-20 11:55
出现错误Traceback (most recent call last):
File ...

好的,出现这个错误是因为要选择的测试集文件数量大于现有的csv文件数量或者数量是负值。我们需要在代码中添加检查来避免这种情况发生。

以下是修改后的代码:

import os
import shutil
import random
from collections import defaultdict

def move_csv_files(source_dir, target_dir):
    # 获取所有csv文件的路径
    csv_files = []
    for root, dirs, files in os.walk(source_dir):
      for file in files:
            if file.endswith(".csv"):
                csv_files.append(os.path.join(root, file))
   
    # 确保有足够的文件进行划分
    if len(csv_files) < 2:
      print("Not enough CSV files to create a test set.")
      return
   
    # 确定测试集的大小,这里假设是20%
    num_test_files = max(2, int(0.2 * len(csv_files)))
    if num_test_files > len(csv_files):
      num_test_files = len(csv_files)

    # 随机选择测试集文件
    test_files = random.sample(csv_files, num_test_files)
   
    # 按照源文件夹结构,将测试集文件移动到目标路径下的相应子文件夹
    for file in test_files:
      rel_path = os.path.relpath(file, source_dir)
      target_path = os.path.join(target_dir, rel_path)
      target_folder = os.path.dirname(target_path)
      
      # 确保目标文件夹存在,如果不存在则创建
      if not os.path.exists(target_folder):
            os.makedirs(target_folder)
            print(f"Created directory: {target_folder}")
      
      # 移动文件
      shutil.move(file, target_path)
      print(f"Moved file {file} to {target_path}")
   
    # 确保每个子文件夹至少有两个测试集文件
    test_files_dict = defaultdict(list)
    for file in test_files:
      rel_path = os.path.relpath(file, source_dir)
      folder = os.path.dirname(rel_path)
      test_files_dict.append(file)
   
    for folder, files in test_files_dict.items():
      if len(files) < 2:
            print(f"Folder {folder} has less than 2 test files. Adding more files...")
            additional_files =
            while len(files) < 2 and additional_files:
                additional_file = additional_files.pop(0)
                rel_path = os.path.relpath(additional_file, source_dir)
                target_path = os.path.join(target_dir, rel_path)
                shutil.move(additional_file, target_path)
                files.append(additional_file)
                print(f"Moved file {additional_file} to {target_path}")

# 示例用法:
source_directory = '/path/to/source_directory'
target_directory = '/path/to/target_directory'

move_csv_files(source_directory, target_directory)

主要改进点:

1. **检查文件数量**:在选择测试集文件之前,确保有足够的文件进行划分。
2. **修正num_test_files计算**:确保计算的测试集文件数量不会超过现有的csv文件数量。

请再次尝试运行这个代码,并确保源路径和目标路径设置正确。如果还有问题,请告诉我!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

1207139945 发表于 2024-6-20 12:03:27

FishC 发表于 2024-6-20 11:56
好的,出现这个错误是因为要选择的测试集文件数量大于现有的csv文件数量或者数量是负值。我们需要在代 ...

import os
import shutil
import random

def move_csv_files(src_folder, dst_folder, percentage):
    if not os.path.exists(dst_folder):
      os.makedirs(dst_folder)

    for root, dirs, files in os.walk(src_folder):
      for file in files:
            if file.endswith('.csv'):
                if random.random() < percentage:
                  src_file = os.path.join(root, file)
                  rel_path = os.path.relpath(root, src_folder)
                  dst_subfolder = os.path.join(dst_folder, rel_path)
                  if not os.path.exists(dst_subfolder):
                        os.makedirs(dst_subfolder)
                  dst_file = os.path.join(dst_subfolder, file)
                  shutil.move(src_file, dst_file)
                  print(f'Moved {src_file} to {dst_file}')

src_folder = '原始文件夹路径'
dst_folder = '目标文件夹路径'
percentage = 0.2

move_csv_files(src_folder, dst_folder, percentage)
直接修改一下这个代码,每次选取两个csv文件移动

FishC 发表于 2024-6-20 12:03:40

1207139945 发表于 2024-06-20 12:03
import os
import shutil
import random

def mov ...

好的,我们在每个子文件夹中至少移动两个 CSV 文件作为测试集。如果文件数量不足,就移动所有文件。以下是改进后的代码:

import os
import shutil
import random

def move_csv_files(src_folder, dst_folder, percentage=0.2):
    if not os.path.exists(dst_folder):
      os.makedirs(dst_folder)

    for root, dirs, files in os.walk(src_folder):
      csv_files =
      if not csv_files:
            continue
      
      num_files = len(csv_files)
      num_test_files = max(2, int(num_files * percentage))
      num_test_files = min(num_test_files, num_files)

      test_files = random.sample(csv_files, num_test_files)
      
      for file in test_files:
            src_file = os.path.join(root, file)
            rel_path = os.path.relpath(root, src_folder)
            dst_subfolder = os.path.join(dst_folder, rel_path)
            if not os.path.exists(dst_subfolder):
                os.makedirs(dst_subfolder)
            dst_file = os.path.join(dst_subfolder, file)
            shutil.move(src_file, dst_file)
            print(f'Moved {src_file} to {dst_file}')

src_folder = '原始文件夹路径'
dst_folder = '目标文件夹路径'

move_csv_files(src_folder, dst_folder)

这个代码做了以下几个改进:

1. 确保每个子文件夹至少移动两个 CSV 文件。
2. 如果文件数量不足,则移动所有文件。
3. 添加了日志信息,便于调试。

你可以将`src_folder`和`dst_folder`替换成实际的路径,然后运行这个脚本来进行文件移动。这样就可以确保每个子文件夹内至少有两个 CSV 文件被移动到目标路径。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 数据集划分