"切"基于其中一个

时间:2018-02-12 05:34:44

标签: python arrays numpy

从概念上讲,我有两个长度相等的列表,一个包含labels,另一个包含data。所以我问this question,没有意识到我真正拥有的是两个numpy数组,而不是两个列表。

我所拥有的是包含cat_01.jpgcat_02.jpgdog_01.jpgdog_02.jpgdog_03.jpgfish_01.jpg等图片的文件夹, ......,tiger_03.jpgzebra_01.jpgzebra_02.jpg。我还有一个成功的程序来读取它们,将每个文件名的一部分解析为labels数组,并将相应的图像数据解析为我的data数组,这样我最终得到的结果如下:

>>> labels
array(['cat', 'cat', 'dog',  ..., 'tiger', 'zebra', 'zebra' ])
>>> type( data )
<class 'numpy.ndarray'>
>>> data[0][0][0]
array([78, 88, 98])

这是有道理的 - 在每个samplecolumnrow),data[ sample ][ row ][ column ]表示(R,G,B)数据点。

我想指定一个搜索标签,例如'dog',并且(从概念上)使用它来生成两个&#34;子列表&#34; - 第一个包含labels列表中的所有(相同)匹配标签,另一个包含来自data的关联图像数据。但是我需要保留原始数据格式,而不是列表,在这种情况下numpy数组(但如果有更通用的,数据不敏感的方法,我很乐意了解它)。我怎么能这样做?

更新:这里有一些特定的测试代码,用于重现我面临的情况,以及基于Stephen Rauch的解决方案草图:

import os, glob
from PIL import Image
import numpy as np
import pandas as pd    # not critical to question

def load_image(file):
  data = np.asarray(Image.open(file),dtype="float")
  return data

MasterClass = ['cat','dog','fsh','grf','hrs','leo','owl','pig','tgr','zbr']
os.chdir('data\\animals')
filelist = glob.glob("*.jpg")

full_labels = np.array([MasterClass.index(os.path.basename(fname)[:3]) for fname in filelist])
full_images = np.array([load_image(fname) for fname in filelist])
# The following sketch a solution, but which leads to incompatible data types
# That is, the test_images differ from the full_images and/or so do the labels
# with regard to the data types involved.
df = pd.DataFrame(dict(label=list(full_labels),data=list(full_images)))
criteria = df['label'] == MasterClass.index('dog')
test_labels = np.array(df[criteria]['label'])
test_images = np.array(df[criteria]['data'])

两个注释:

  • 最初我写的时候有文件名&#34;比如&#34; tiger_03.jpg,我正在消除对现实的迷惑。事实上,上面的代码需要像tgr03.jpg这样的文件名,而我最终使用的标签列表甚至不是['cat', 'cat', 'dog', ...],而是MasterClass列表中的索引列表 - 是,[0, 0, 1, ...]
  • 出于测试目的,文件的内容实际上并不重要,只要它们是有效(JPEG)图像即可。您可以轻松地使用少量(相同)文件在具有少量不同名称的文件夹中进行测试。

问题是:如何让test_labelstest_images采用与原始full_labelsfull_images相同的格式,但会基于选择{{1}像上面描绘的那个?这个代码目前并没有达到这种级别的数据兼容性 - 它没有实现严格的&#34;切片&#34;功能

3 个答案:

答案 0 :(得分:1)

如果你可以使用熊猫,那么这种事情非常好。

代码:

如果您已有数据框,则可以执行以下操作:

# build a logical condition
have_dog = df['animal_label'] == 'dog'

# select the data when that condition is true
print(df[have_dog])

测试代码:

import pandas as pd
import numpy as np

animal_label = ['cat', 'cat', 'dog', 'dog', 'dog', 'fish', 'fish', 'giraffe']
data = [0.3, 0.1, 0.9, 0.5, 0.4, 0.3, 0.2, 0.8]
data = [np.array((x,) * 3) for x in data]

df = pd.DataFrame(dict(animal_label=animal_label, data=data))
print(df)

have_dog = df['animal_label'] == 'dog'
print(df[have_dog])

结果:

  animal_label             data
0          cat  [0.3, 0.3, 0.3]
1          cat  [0.1, 0.1, 0.1]
2          dog  [0.9, 0.9, 0.9]
3          dog  [0.5, 0.5, 0.5]
4          dog  [0.4, 0.4, 0.4]
5         fish  [0.3, 0.3, 0.3]
6         fish  [0.2, 0.2, 0.2]
7      giraffe  [0.8, 0.8, 0.8]

  animal_label             data
2          dog  [0.9, 0.9, 0.9]
3          dog  [0.5, 0.5, 0.5]
4          dog  [0.4, 0.4, 0.4]

答案 1 :(得分:0)

如果我理解你的问题,可以通过这样切片来完成:

selector = 'fish'
matching_labels = labels[labels==selector]
matching_data = data[labels==selector]

或者,您可以使用上一个问题中答案的方法,并通过alist

将列表alist = numpy.array(alist)设为一个numpy数组

答案 2 :(得分:0)

基于Stephen Rauch's answer to my earlier simpler question,可以按如下方式解决此问题:

# assume full_labels and full_images exist as per test code in updated question
tuples = (x for x in zip(list(full_labels),list(full_images)) if x[0] == MasterClass.index('dog'))
xlabels,ximages = map(list, zip(*tuples))
test_labels = np.array(xlabels)
test_images = np.array(ximages)