Python np.append не работает со значением словаря типа numpy .ndarray - PullRequest
1 голос
/ 10 апреля 2020

У меня есть функция, которая из двух массивов numpy преобразует их в словарь следующим образом

def seggregate_based_on_y(X,y):
    dictionary={}
    for index in range(len(y)):
        if y[index] in dictionary.keys():
            np.append(dictionary[y[index]],X[index])
        else:
            dictionary[y[index]]=np.array([X[index]])
    return dictionary

для следующего ввода

X=np.array([[1,1],[2,2],[3,3],[4,4],[5,5]])
y=np.array([2,3,2,3,4])
d=seggregate_based_on_y(X,y)
print(d)

Я ожидаю, что 'd' будет {2: array([[1, 1],[3,3]]), 3: array([[2, 2],[4,4]]), 4: array([[5, 5]])} но я получаю 'd' равным {2: array([[1, 1]]), 3: array([[2, 2]]), 4: array([[5, 5]])}, то есть оператор if не работает. Что должно быть сделано?

Ответы [ 4 ]

1 голос
/ 10 апреля 2020

defaultdict делает этот вид коллекции легко:

In [268]: from collections import defaultdict                                                          
In [269]: x = [[1,1],[2,2],[3,3],[4,4],[5,5]]                                                          
In [270]: y = [2,3,2,3,4]                                                                              
In [271]: dd = defaultdict(list)                                                                       
In [272]: for i,j in zip(y, x): 
     ...:     dd[i].append(j) 
     ...:                                                                                              
In [273]: dd                                                                                           
Out[273]: defaultdict(list, {2: [[1, 1], [3, 3]], 3: [[2, 2], [4, 4]], 4: [[5, 5]]})

Если результатом должен быть массив, а не список, его можно преобразовать с помощью:

In [274]: d = {k: np.array(dd[k]) for k in dd}                                                         
In [275]: d                                                                                            
Out[275]: 
{2: array([[1, 1],
        [3, 3]]), 3: array([[2, 2],
        [4, 4]]), 4: array([[5, 5]])}

Добавление списка быстрее, чем np.append (или любая из функций семейства numpy concatenate). Добавление списка работает на месте.

defaultdict может создать массив напрямую (но я ожидаю, что это будет медленнее):

In [280]: dd = defaultdict(lambda:np.zeros((0,2),int))                                                 
In [281]: for i,j in zip(y, x): 
     ...:     dd[i] = np.vstack((dd[i],j)) 
     ...:                                                                                              
In [282]: dd                                                                                           
Out[282]: 
defaultdict(<function __main__.<lambda>()>, {2: array([[1, 1],
                    [3, 3]]), 3: array([[2, 2],
                    [4, 4]]), 4: array([[5, 5]])})
1 голос
/ 10 апреля 2020

Попробуйте это

import numpy as np

def seggregate_based_on_y(X,y):
    dictionary={}
    for index in range(len(y)):
        if y[index] in dictionary.keys():
            z = np.append(dictionary[y[index]], X[index])
            dictionary[y[index]] = z.reshape(z.size // 2, 2)

        else:
            dictionary[y[index]]=np.array([X[index]])
    return dictionary

X=np.array([[1,1],[2,2],[3,3],[4,4],[5,5]])
y=np.array([2,3,2,3,4])
d=seggregate_based_on_y(X,y)
print(d)

Вывод:

{2: array([[1, 1],[3, 3]]), 3: array([[2, 2],[4, 4]]), 4: array([[5, 5]])}
1 голос
/ 10 апреля 2020

Во-первых, как говорится в комментариях, вы должны присвоить вашему словарю новое значение. См. Приведенное ниже исправление:

def seggregate_based_on_y(X,y):
    dictionary={}
    for index in range(len(y)):
        if y[index] in dictionary.keys():
            dictionary[y[index]] = np.append(dictionary[y[index]],X[index])
        else:
            dictionary[y[index]]=np.array([X[index]])
    return dictionary

При заданных данных выводится:

{2: array([1, 1, 3, 3]), 3: array([2, 2, 4, 4]), 4: array([[5, 5]])}

Это не то же самое, что ожидаемые результаты, потому что np.append добавится к тому же вектору. Чтобы получить требуемый вывод, используйте np.vstack

def seggregate_based_on_y(X,y):
    dictionary={}
    for index in range(len(y)):
        if y[index] in dictionary.keys():
            dictionary[y[index]] = np.vstack((dictionary[y[index]],X[index]))
        else:
            dictionary[y[index]]=np.array([X[index]])
    return dictionary

здесь вывод:

{2: array([[1, 1],
       [3, 3]]), 3: array([[2, 2],
       [4, 4]]), 4: array([[5, 5]])}

Надеюсь, это поможет.

1 голос
/ 10 апреля 2020

вы можете использовать встроенную функцию zip:

def seggregate_based_on_y(X,y):
    d = {}
    for k, v in zip(y, X):
        if k in d:
            d[k] = np.append(d[k], v.reshape(1, 2), axis=0)
        else:
            d[k] = v.reshape(1, 2)

    return d


X=np.array([[1,1],[2,2],[3,3],[4,4],[5,5]])
y=np.array([2,3,2,3,4])
print(seggregate_based_on_y(X,y))

вывод:

{2: array([[1, 1],
        [3, 3]]), 3: array([[2, 2],
        [4, 4]]), 4: array([[5, 5]])}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...