os.listdir()-根据条件从返回的列表中随机选择

时间:2018-09-25 07:15:06

标签: python list random shuffle listdir

我有一个目录,其中包含来自三个不同域的数千张图像

假设文件名为xxx_A.png和yyy_B.png和zzz_C.png 每个域都有数千个

os.listdir()将返回目录中所有图像名称的列表

然后我要根据某些百分比过滤此列表

示例: 我指定我要在这数千张图片中只包含100张混洗的图片,其中30%来自domainA,30%来自domainB和40%来自domainC

因此,只要给定一定数量,我就具有这些百分比,然后选择x个随机图像(肯定已经基于图像名称,因为它们已经被指定),这将是新列表

示例:

输入:

['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张图像,其中A域占30%,B域占30%,C域占40%

输出:

 ['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 :(得分:1)

下面是我定义的函数。正如Martin所说,math.ceil可能是用来获取文件数量的最佳函数(因此,获取的数量不会少于所需的数量)。另外,您将希望采样时不进行替换(这意味着您不想重复文件名),因此您不应该像Rakesh那样使用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']

您还可以在return语句之前调用random.shuffle(shuffled_list),以随机排列输出列表。

答案 1 :(得分:0)

这是一种可能的方法:

  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上测试

答案 2 :(得分:0)

这是一种方法。我正在使用字典将图像从不同的域中分离出来,然后计算每个域中所需的图像数。

演示:

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']