Выберите случайным образом x файлов в подкаталогах - PullRequest
1 голос
/ 19 февраля 2020

Мне нужно взять ровно 10 файлов (изображений) в наборе данных случайным образом, но этот набор данных имеет иерархическую структуру.

Поэтому мне нужно, чтобы в каждом подкаталоге, содержащем изображения, содержалось только 10 из них случайным образом. Есть ли простой способ сделать это, или я должен сделать это вручную?

def getListOfFiles(dirName):
    ### create a list of file and sub directories 
    ### names in the given directory 
    listOfFile = os.listdir(dirName)
    allFiles = list()
    ### Iterate over all the entries
    for entry in listOfFile:

        ### Create full path
        fullPath = os.path.join(dirName, entry)
        ### If entry is a directory then get the list of files in this directory 
        if os.path.isdir(fullPath):
            allFiles = allFiles + getListOfFiles(fullPath)
        else:
            allFiles.append(random.sample(fullPath, 10))
    return allFiles

dirName = 'C:/Users/bla/bla'

### Get the list of all files in directory tree at given path
listOfFiles = getListOfFiles(dirName)

with open("elements.txt", mode='x') as f:
    for elem in listOfFiles:
        f.write(elem + '\n')

1 Ответ

0 голосов
/ 19 февраля 2020

Хороший подход к выборке из списка каталогов неизвестного размера - использовать Выборка резервуара . При таком подходе вам не нужно запускать заранее и перечислять все файлы в каталоге. Прочитайте это один за другим и образец. Это работает даже тогда, когда вам нужно сэмплировать фиксированное количество файлов в нескольких каталогах.

Было бы хорошо использовать код сканирования каталогов на основе генератора, который выбирает один файл за раз, поэтому вы не используете gobs оперативной памяти для хранения всех имен файлов.

Вдоль строк (NB! нежелательный код!)

import numpy as np
import os

def ResSampleFiles(dirname, N):
    """pick N files from directory"""

    sampled_files = list()
    k = 0
    for item in scandir(dirname):
        if item.is_dir():
            continue
        full_path = os.path.join(dirname, item.name)
        if k < N:
            sampled_files.append(full_path)
        else:
            idx = np.random.randint(0, k+1)
            if (idx < N):
                sampled_files[idx] = full_path
        k += 1

    return sampled_files
...