Измените dtype набора значений в массиве numpy на месте - PullRequest
0 голосов
/ 31 марта 2020

Буду очень признателен за помощь в следующем. Я читаю данные из файла CSV в списки списков, а затем изменяю их на массив numpy. Однако я действительно изо всех сил пытаюсь изменить набор значений в массиве numpy на числа с плавающей точкой, так как я хотел бы добавить набор чисел для каждой строки и вставить сумму как новый элемент в каждую строку.

Я могу изменить их и создать копию измененного типа данных, но я не могу сделать это на месте (в исходном массиве numpy).

Вот небольшой пример того, как выглядят данные из CSV и чего я пытаюсь достичь.

list_of_lists = [["Africa", "1990", "0", "", "32.6"], ["Asia", "2006", "32.4", "5.5", "46.6"],
                 ["Europe", "2011", "5.4", "", "55.4"]]

array = np.array(list_of_lists)

array[array == ""] = np.nan

print(array)

# This doesnt change it in place

array[:, 2:].astype(np.float32, copy=False)

# And this doesnt as well

array[:, 2:] = array[:,2:].astype(np.float32)

Я прочитал несколько вопросов, похожих на этот, но ни один из методы работали для меня. Я думал, что это будет так же просто, как установить copy = False, но, видимо, это не так ...

Я был бы очень признателен за руку, и если бы кто-то мог мне это объяснить.

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Вы не можете изменить dtype на месте.

In [59]: arr = np.array(list_of_lists)                                                         
In [60]: arr                                                                                   
Out[60]: 
array([['Africa', '1990', '0', '', '32.6'],
       ['Asia', '2006', '32.4', '5.5', '46.6'],
       ['Europe', '2011', '5.4', '', '55.4']], dtype='<U6')

Общим типом ввода является строка.

, заменяя "" на nan, вставляет строковое представление в массиве:

In [62]: arr[arr == ""] = np.nan                                                                                       
In [63]: arr                                                                                   
Out[63]: 
array([['Africa', '1990', '0', 'nan', '32.6'],
       ['Asia', '2006', '32.4', '5.5', '46.6'],
       ['Europe', '2011', '5.4', 'nan', '55.4']], dtype='<U6')

Посмотрите на часть базового буфера данных:

In [64]: arr.tobytes()                                                                         
Out[64]: b'A\x00\x00\x00f\x00\x00\x00r\x00\x00\x00i\x00\x00\x00c\x00\x00\x00a\x00\x00\x001\x00\x00\x009\x00\x00\x009\x00\x00\....'

См. фактические символы.

Срез массива view, но преобразование astype - это новый массив с собственным буфером данных.

In [65]: arr[:,2:]                                                                             
Out[65]: 
array([['0', 'nan', '32.6'],
       ['32.4', '5.5', '46.6'],
       ['5.4', 'nan', '55.4']], dtype='<U6')
In [66]: arr[:,2:].astype(float)                                                               
Out[66]: 
array([[ 0. ,  nan, 32.6],
       [32.4,  5.5, 46.6],
       [ 5.4,  nan, 55.4]])

Невозможно записать Out[66] обратно в arr без его преобразования обратно в строку.

Вы можете создать массив dtype объекта:

In [67]: arr = np.array(list_of_lists, dtype=object)                                           
In [68]: arr                                                                                   
Out[68]: 
array([['Africa', '1990', '0', '', '32.6'],
       ['Asia', '2006', '32.4', '5.5', '46.6'],
       ['Europe', '2011', '5.4', '', '55.4']], dtype=object)
In [69]: arr = np.array(list_of_lists, dtype=object)                                           
In [70]: arr[arr == ""] = np.nan                                                               
In [71]: arr                                                                                   
Out[71]: 
array([['Africa', '1990', '0', nan, '32.6'],
       ['Asia', '2006', '32.4', '5.5', '46.6'],
       ['Europe', '2011', '5.4', nan, '55.4']], dtype=object)
In [72]: arr[:,2:] = arr[:,2:].astype(float)                                                   
In [73]: arr                                                                                   
Out[73]: 
array([['Africa', '1990', 0.0, nan, 32.6],
       ['Asia', '2006', 32.4, 5.5, 46.6],
       ['Europe', '2011', 5.4, nan, 55.4]], dtype=object)

dtype остается объектом, но тип элементов может меняться - это потому, что объект dtype является прославленным (или униженным) списком. Вы получаете некоторую гибкость, но теряете большую часть скорости numpy цифр c.

Структурированный массив (составной тип d), как показано в другом ответе, - другая возможность. Этот тип массива легко создать при загрузке csvnp.genfromtxt). Вы все еще не можете изменить dtypes на месте. И вы не можете выполнять математику для полей структурированного массива.

pandas

In [153]: df = pd.DataFrame(list_of_lists)                                                     
In [154]: df                                                                                   
Out[154]: 
        0     1     2    3     4
0  Africa  1990     0       32.6
1    Asia  2006  32.4  5.5  46.6
2  Europe  2011   5.4       55.4
In [156]: df.info()                                                                            
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 5 columns):
0    3 non-null object
1    3 non-null object
2    3 non-null object
3    3 non-null object
4    3 non-null object
dtypes: object(5)
memory usage: 248.0+ bytes

Преобразовать dtypes столбца:

In [158]: df[2].astype(float)   
In [162]: df[4]=df[4].astype(float) 

Столбцу 3 требуется nan преобразование, прежде чем мы сможем его преобразовать.

In [164]: df                                                                                   
Out[164]: 
        0     1     2    3     4
0  Africa  1990   0.0       32.6
1    Asia  2006  32.4  5.5  46.6
2  Europe  2011   5.4       55.4
In [165]: df.dtypes                                                                            
Out[165]: 
0     object
1     object
2    float64
3     object
4    float64
dtype: object

Здесь есть лучшие pandas программисты; Я сосредоточился больше на numpy.

1 голос
/ 31 марта 2020

Кажется, вам нужен структурированный массив для обработки нескольких типов данных

list_of_lists = [["Africa", "1990", "0", "", "32.6"], ["Asia", "2006", "32.4", "5.5", "46.6"],
                 ["Europe", "2011", "5.4", "", "55.4"]]

temp = np.array(list_of_lists)
temp[temp==''] = 0

dtypes = np.dtype([('name','S10'),
    ('val1', np.float),
    ('val2',np.float),
    ('val3',np.float),
    ('val4',np.float)])

array = np.array(list(map(tuple, temp)), dtype=dtypes)

# Now you can modify the structured array
array[['val3', 'val4']]=20
array[0]['name'] = 'Australia'

Проблема в том, что вы можете притворяться, что это столбцы, но ответ - нет, это просто структура и форма (3,), я бы рекомендовал перейти на pandas фрейм данных.

import pandas as pd

array = pd.DataFrame(list_of_lists)
array.replace('', '0', inplace=True)
array[data.columns[2:]] = array[array.columns[2:]].astype(float)

array.dtypes

# 0 object
# 1 object
# 2 float64
# 3 float64
# 4 float64
# dtype: object
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...