os.listdir() - 根据条件从返回的列表中随机选择
os.listdir() - choose randomly from the returned list based on a condition
我有一个包含来自三个不同域的数千张图像的目录
假设文件名为 xxx_A.png 和 yyy_B.png 以及 zzz_C.png
每个域都有数千人
os.listdir()
将 return 目录中所有图像名称的列表
然后我想根据某些百分比过滤此列表
示例:
我指定我想要在这数千张图像中,只有 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 张图片,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']
我该怎么做?
这是一种可能的方法:
首先使用 defaultdict(list)
根据字母将所有文件名拆分为域。例如字典看起来像:
{'A' : ['file1_A.jpg', 'file2_A.jpg'], 'B' : ['file1_B.jpg']}
对于每个域,使用 random.sample()
to randomly take the required number of files from the domain into an output list. math.ceil()
用于确保始终向上舍入以确保始终存在足够的文件。
最后,打乱组合输出列表(如果需要)并确保文件总数正确。
这将导致输出具有来自每个域的随机元素的精确分布。
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
上测试
这是一种方法。我正在使用字典将图像从不同域中分离出来,然后计算每个域所需的图像数量。
演示:
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']
下面是我定义的函数。正如 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)
来打乱输出列表。
我有一个包含来自三个不同域的数千张图像的目录
假设文件名为 xxx_A.png 和 yyy_B.png 以及 zzz_C.png 每个域都有数千人
os.listdir()
将 return 目录中所有图像名称的列表
然后我想根据某些百分比过滤此列表
示例: 我指定我想要在这数千张图像中,只有 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 张图片,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']
我该怎么做?
这是一种可能的方法:
首先使用
defaultdict(list)
根据字母将所有文件名拆分为域。例如字典看起来像:{'A' : ['file1_A.jpg', 'file2_A.jpg'], 'B' : ['file1_B.jpg']}
对于每个域,使用
random.sample()
to randomly take the required number of files from the domain into an output list.math.ceil()
用于确保始终向上舍入以确保始终存在足够的文件。最后,打乱组合输出列表(如果需要)并确保文件总数正确。
这将导致输出具有来自每个域的随机元素的精确分布。
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
上测试这是一种方法。我正在使用字典将图像从不同域中分离出来,然后计算每个域所需的图像数量。
演示:
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']
下面是我定义的函数。正如 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)
来打乱输出列表。