如何从Train,Test和Validation文件夹中的多个文件夹中拆分和复制文件

时间:2019-01-26 14:45:24

标签: python random shutil

我有一个数据集,由130个文件夹组成,每个文件夹包含32张照片。

我想从每个文件夹中将照片(用于训练的26张照片,用于测试的3张照片以及用于验证的3张照片)随机复制到火车,验证和测试文件夹中的相应子文件夹(001、002、003 ...)。 所以我会有这样的东西:

  
      
  • 火车套

         
        
    • 001(文件夹包含26张照片)
    •   
    • 002
    •   
    • 003
    •   
    • ....
    •   
  •   
  • 验证集

         
        
    • 001(文件夹包含3张照片)
    •   
    • 002
    •   
    • 003
    •   
    • ....
    •   
  •   
  • 火车套

         
        
    • 001(文件夹包含3张照片)
    •   
    • 002
    •   
    • 003
    •   
    • ....
    •   
  •   

这是代码:

import random
import shutil

n_photo_train = 26
n_photo_validation = 3
n_photo_test = 3

for idx in range(130):

    source = '/Users/john/photodb_original/{d:03d}'.format(d=(idx + 1))
    dest_train = '/Users/john/photodb_sets/Train/{d:03d}'.format(d=(idx + 1))
    dest_validation = '/Users/john/photodb_sets/Validation/{d:03d}'.format(d=(idx + 1))
    dest_test = '/Users/john/photodb_sets/Test/{d:03d}'.format(d=(idx + 1))

    files = random.choice(os.listdir(source))
    photo_train = files[:n_photo_train]
    photo_test = files[26:29]
    photo_val = files[29:]

    shutil.copyfile(os.path.join(source, photo_train), dest_train)
    shutil.copyfile(os.path.join(source, photo_val), dest_validation)
    shutil.copyfile(os.path.join(source, photo_test), dest_test)

我收到此错误:IsADirectoryError: [Errno 21] Is a directory: '/Users/john/photodb_original/001/'

我是否使用了不正确的shutil.copyfile?否则,有没有办法以更紧凑和清晰的方式编写代码?

2 个答案:

答案 0 :(得分:2)

random.choice(os.listdir(source))将仅返回single element-当您尝试索引该字符串时,您将获得一个空字符串,而os.path.join将返回目录路径-这将导致您的异常。

从您的代码看来,您打算使用random.shuffle。请注意,如果您使用随机播放,它将使列表发生变化,因此您的代码应分为两个命令:

files = os.listdir(source)
random.shuffle(files)

答案 1 :(得分:1)

我认为您需要创建目录以在其中复制文件,或者在缺少目录缺失的异常时,请尝试先创建目录,然后再尝试复制文件。无论如何,这是我认为可以满足您需求的示例代码。

import os
from random import shuffle
from shutil import copyfile, rmtree

org = os.path.realpath('org')
trn = os.path.realpath('trn')
tst = os.path.realpath('tst')
val = os.path.realpath('val')
# How split will be performed 26 3 3
rnd = [trn]*26+[tst]*3+[val]*3

rmtree(trn)
rmtree(tst)
rmtree(val)
rmtree(org)

# CREATE DUMMY DATA
for i in range(1, 131):
    d = os.path.join(org, "{:03d}".format(i))
    os.makedirs(d, exist_ok=True)
    for f in range(1, 33):
        f = os.path.join(d, "{:02d}".format(f))
        open(f, 'a').close()

# ACTUAL STUFF
for d in os.listdir(org):
    os.makedirs(os.path.join(trn, d))
    os.makedirs(os.path.join(tst, d))
    os.makedirs(os.path.join(val, d))
    files = os.listdir(os.path.join(org,d))
    shuffle(rnd)
    for f, trg in zip(os.listdir(os.path.join(org,d)),rnd):
        scr = os.path.join(org,d,f)
        dst = os.path.join(trg,d,f)
        copyfile(scr,dst)