os.listdir () - выбрать случайным образом из возвращенного списка на основе условия - PullRequest
0 голосов
/ 25 сентября 2018

У меня есть каталог, содержащий тысячи изображений из трех разных доменов

Допустим, имена файлов: xxx_A.png, yyy_B.png и zzz_C.png, тысячи из каждого домена

os.listdir() вернет список для всех имен изображений в каталоге

Затем я хочу отфильтровать этот список по некоторым процентам

Пример: я указываю, что хочу получить из этих тысячизображений, только 100 перетасованных изображений, где 30% из них будут из домена A, 30% из домена B и 40% домена C

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

Пример:

Ввод:

['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']

Я хочу 12 изображений, 30% из домена A, 30% из домена B и 40% из домена C

Вывод:

 ['1_C.png', '10_C.png', '2_B.png', '4_A.png', '3_A.png', '9_C.png', '7_C.png', '6_A.png', '8_B.png', '10_B.png', '3_C.png', '5_C.png']

Как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 25 сентября 2018

Это один из подходов.Я использую словарь, чтобы отделить изображение от разных доменов, а затем рассчитать количество изображений, необходимых для каждого домена.

Демонстрация:

import random    

inputData = ['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']

d = {"A": [], "B":[], "C":[]}
#for i in os.listdir("path"):
for i in inputData:           #Group images by domain. 
    if "A" in i:
        d["A"].append(i)
    elif "B" in i:
        d["B"].append(i)
    else:
        d["C"].append(i)

percentage = {"A": 30, "B": 30, "C": 60} 

res = []
for k, v in d.items():
    res.extend([random.choice(v) for i in range(int((percentage[k] * len(v)) / 100.0))])
print(res) 

Выход:

['7_A.png', '8_A.png', '9_A.png', '6_C.png', '8_C.png', '9_C.png', '7_C.png', '9_C.png', '7_C.png', '1_B.png', '6_B.png', '2_B.png']
0 голосов
/ 25 сентября 2018

Ниже приведена функция, которую я определил.Как сказал Мартин, math.ceil, вероятно, лучшая функция для получения количества файлов (поэтому вы не получите меньше желаемого количества).Кроме того, вы захотите сделать выборку без замены (то есть вы не хотите повторять имена файлов), поэтому вы не должны использовать random.choice, как это сделал Ракеш (как выборки random.choice с заменой).Random.shuffle позволяет избежать этой проблемы.

Ввод:

import random
import math
os_dir_list= ['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']       
def shuffle_pick(os_dir_list,length, tuple_list):
    shuffled_list = []
    for letter,percent in tuple_list:
        sub_list = [img for img in os_dir_list if img.endswith(letter + '.png')]
        random.shuffle(sub_list)
        num = int(math.ceil(len(sub_list)*percent/100))
        shuffled_list += sub_list[:num]
    return shuffled_list[:length]

print(shuffle_pick(os_dir_list, 12, [('A',30),('B',30),('C',60)]))

Вывод:

['1_A.png', '5_A.png', '3_A.png', '6_A.png', '1_B.png', '7_B.png', '9_B.png', '5_B.png', '10_C.png', '4_C.png', '3_C.png', '9_C.png']

Вы также можете вызвать random.shuffle(shuffled_list) перед оператором возврата, чтобы перетасоватьсписок вывода.

0 голосов
/ 25 сентября 2018

Вот один из возможных подходов:

  1. Сначала разбейте все имена файлов на домены на основе буквы, используя defaultdict(list).например, словарь, похожий на:

    {'A' : ['file1_A.jpg', 'file2_A.jpg'], 'B' : ['file1_B.jpg']}
    
  2. Для каждого домена используйте random.sample(), чтобы случайным образом взять необходимое количество файлов из домена в список вывода,math.ceil() используется для того, чтобы обеспечить достаточное количество файлов, всегда округляя их вверх.

  3. Наконец, перемешайте комбинированный список вывода (если требуется) и убедитесь, чтоуказано правильное общее количество файлов.

Это приведет к выводу с точным распределением случайных элементов из каждого домена.

from collections import defaultdict
import random
import math

domains = defaultdict(list)

files = ['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']

for file in files:
    domains[file[-5]].append(file)

total_required = 12
output = []    

for key, percentage in (('A', 30.0), ('B', 30.0), ('C', 40.0)):
    len_required = int(math.ceil(percentage * total_required / 100.0))
    output.extend(random.sample(domains[key], len_required))

random.shuffle(output)
output = output[:total_required]

print(len(output), output)

Предоставление возможноговывод:

12 ['6_B.png', '2_B.png', '3_B.png', '10_A.png', '1_A.png', '6_A.png', '2_C.png', '1_B.png', '1_C.png', '3_C.png', '2_A.png', '10_C.png']    

Проверено на Python 3.6.6

...