Python 如何从train、test和validation文件夹中的多个文件夹中拆分和复制文件
我有一个数据集,由130个文件夹组成,每个文件夹包含32张照片 从每个文件夹中,我想将这些照片(26张用于培训,3张用于测试,3张用于验证)随机复制到train,validation and test文件夹中相应的子文件夹(001,002,003…)中。 所以我会有这样的东西:Python 如何从train、test和validation文件夹中的多个文件夹中拆分和复制文件,python,random,shutil,Python,Random,Shutil,我有一个数据集,由130个文件夹组成,每个文件夹包含32张照片 从每个文件夹中,我想将这些照片(26张用于培训,3张用于测试,3张用于验证)随机复制到train,validation and test文件夹中相应的子文件夹(001,002,003…)中。 所以我会有这样的东西: 列车组 001(文件夹包含26张照片) 002 003 验证集 001(文件夹包含3张照片) 002 003 列车组 001(文件夹包含3张照片) 002 003 代码如下: import rand
- 列车组
- 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)
我得到这个错误:isDirectoryError:[Errno 21]是一个目录:'/Users/john/photodb_original/001/'
我是否错误地使用了shutil.copyfile?否则,有没有一种方法可以更紧凑、更清晰地编写代码?random.choice(os.listdir(source))
将只返回一个-当您尝试索引此字符串时,您将得到一个空字符串,os.path.join
将返回目录路径-这将导致异常
从您的代码来看,您的目标似乎是使用。请注意,如果您使用的是shuffle,它会改变列表,因此您的代码应该拆分为两个命令:
files = os.listdir(source)
random.shuffle(files)
random.choice(os.listdir(source))
将只返回一个-当您尝试索引此字符串时,您将得到一个空字符串,os.path.join
将返回目录路径-这将导致您的异常
从您的代码来看,您的目标似乎是使用。请注意,如果您使用的是shuffle,它会改变列表,因此您的代码应该拆分为两个命令:
files = os.listdir(source)
random.shuffle(files)
我认为您需要创建目录来复制其中的文件,或者当您遇到关于缺少目录的异常时,请尝试先创建目录,然后再次尝试复制文件。无论如何,这里有一个示例代码,我认为它符合您的要求
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)
我认为您需要创建目录来复制其中的文件,或者当您遇到关于缺少目录的异常时,请尝试先创建目录,然后再次尝试复制文件。无论如何,这里有一个示例代码,我认为它符合您的要求
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)
谢谢现在我有另一个问题。我在运行shutil.copyfile(os.path.join(source,photo\u train,dest\u train)时得到了这个错误
TypeError:join()参数必须是str或bytes,而不是'list'
,那么,使用的index slice命令:files[:n\u photo\u train]
将返回一个iterable。而copyfile只接受一个文件,您可能希望使用以下理解来迭代和复制该文件:[sutil.copyfile(file,dest\u train)for file in os.path.join(source,photo\u train)]
谢谢。现在我有另一个问题。我在运行shutil.copyfile(os.path.join(source,photo\u train,dest\u train)时得到了这个错误TypeError:join()参数必须是str或bytes,而不是'list'
,那么,使用的index slice命令:files[:n\u photo\u train]
将返回一个iterable。而copyfile只接受一个文件,您可能希望使用以下理解来迭代和复制该文件:[sutil.copyfile(file,dest\u train)for file in os.path.join(source,photo\u train)]
谢谢!我忘了发布那部分代码,但我已经创建了文件夹001002。在“培训、测试和验证”文件夹中。我不明白你在“#如何执行拆分”部分做了什么。它创建目标目录路径的列表。基本上26项用于培训,3项用于测试,3项用于验证。在循环每个包含32张图片的目录时,您可以洗牌列表,以确定项目是否属于测试、验证和培训集。谢谢!我忘了发布那部分代码,但我已经创建了文件夹001002。在“培训、测试和验证”文件夹中。我不明白你在“#如何执行拆分”一节中做了什么。它创建了一个目标目录路径列表。基本上26个项目用于培训,3个项目用于测试,3个项目用于验证。在循环每个包含32张图片的目录时,你洗牌列表以确定项目属于测试、验证和培训集。