2016-03-06 5 views
2

У меня есть матрица данных 50000 x 784 (50000 образцов и 784 функций) и соответствующий вектор класса 50000 x 1 (классы - целые числа 0-9). Я ищу эффективный способ группировки матрицы данных в 10 матриц данных и векторов классов, каждая из которых имеет только данные для определенного класса 0-9.Данные по подготовке раздела по классам в NumPy

Я не могу найти элегантный способ сделать это, кроме как просто прокручивать матрицу данных и таким образом строить 10 других матриц.

Кто-нибудь знает, есть ли чистый способ сделать это с чем-то в scipy, numpy, или sklearn?

+0

Лучшее решение зависит от параметров, таких как размер данных (вся матрица вписывается в память?), Форма данных (массив данных numpy, строки, ....), ..... Благодаря точным данным пунктам. –

ответ

2

Если data и labels матрицы в Numpy формате, вы можете сделать:

data_class_3 = data[labels == 3, :] 

Если их нет, превратить их в Numpy формате:

import numpy as np 
data = np.array(data) 
labels = np.array(labels) 
data_class_3 = data[labels == 3, :] 

Вы можете петли и сделать это для всех этикеток, если хотите. Что-то вроде этого:

import numpy as np 
split_classes = np.array([data[labels == i, :] for i in range(10)]) 
+0

Я не получаю ';:' in 'data [labels == 3,:]', не так ли много индексов? Недостаточно с 'data [labels == 3]'? –

+2

Да, этого достаточно в 2D-случае. Когда у вас больше измерений, он становится сложным, и я привык к тому, чтобы быть явным. – mprat

+0

Если вы не хотите указывать диапазон, вы можете использовать: 'np.array ([data [labels == i] для i в np.unique (метки)])' –

2

Вероятно, чистый способ сделать это в NumPy, особенно если у вас есть много классов, через сортировки:

SAMPLES = 50000 
FEATURES = 784 
CLASSES = 10 
data = np.random.rand(SAMPLES, FEATURES) 
classes = np.random.randint(CLASSES, size=SAMPLES) 

sorter = np.argsort(classes) 
classes_sorted = classes[sorter] 
splitter, = np.where(classes_sorted[:-1] != classes_sorted[1:]) 
data_splitted = np.split(data[sorter], splitter + 1) 

data_splitted будет список массивов, один для каждого класс найден в classes. Запуск выше кода с SAMPLES = 10, FEATURES = 2 и CLASSES = 3 я получаю:

>>> data 
array([[ 0.45813694, 0.47942962], 
     [ 0.96587082, 0.73260743], 
     [ 0.70539842, 0.76376921], 
     [ 0.01031978, 0.93660231], 
     [ 0.45434223, 0.03778273], 
     [ 0.01985781, 0.04272293], 
     [ 0.93026735, 0.40216376], 
     [ 0.39089845, 0.01891637], 
     [ 0.70937483, 0.16077439], 
     [ 0.45383099, 0.82074859]]) 

>>> classes 
array([1, 1, 2, 1, 1, 2, 0, 2, 0, 1]) 

>>> data_splitted 
[array([[ 0.93026735, 0.40216376], 
     [ 0.70937483, 0.16077439]]), 
array([[ 0.45813694, 0.47942962], 
     [ 0.96587082, 0.73260743], 
     [ 0.01031978, 0.93660231], 
     [ 0.45434223, 0.03778273], 
     [ 0.45383099, 0.82074859]]), 
array([[ 0.70539842, 0.76376921], 
     [ 0.01985781, 0.04272293], 
     [ 0.39089845, 0.01891637]])] 

Если вы хотите, чтобы убедиться, что сорт является стабильным, т.е. точек данных в одном классе остается в том же относительном порядке после сортировки, вы будете необходимо указать sorter = np.argsort(classes, kind='mergesort').

+0

Из любопытства, почему необходимо сортировать, а не индексировать напрямую? – mprat

+1

Для этого конкретного случая всего 10 классов ваше решение может быть лучшим выбором. Но если у вас много классов, вам нужно перебирать весь массив один раз для каждого класса.Очень скоро подход O (n log n) с сортировкой будет бить O (m n), который идет с индексацией. – Jaime

1

После @Jaime Numpy оптимального ответа, я предлагаю вам pandas, специализирующиеся на манипуляциях данных:

import pandas 
df=pandas.DataFrame(data,index=classes).sort_index() 

df.loc[i] тогда ваш класс i.

, если вы хотите получить список, просто сделать

metadata=[df.loc[i].values for i in range(10)] 

так metadata[i] -подмножество вы хотите, или сделать панель с pandas. Все это основано на массивах numpy, поэтому эффективность сохраняется.