sys.getsizeof
- это один из способов проверки использования памяти, хотя вы должны использовать его с умом, понимая, что именно он измеряет. Для массивов это работает довольно хорошо.
Массив без каких-либо элементов:
In [28]: sys.getsizeof(np.array([],'U6'))
Out[28]: 96
In [29]: sys.getsizeof(np.array(['smile','smile1'],'U6'))
Out[29]: 144
In [30]: sys.getsizeof(np.array(['smile','smile1'],'S6'))
Out[30]: 108
При 2 строках 'U6' размер увеличивается на 48,4 байта / символ * 2 элемента * 6 символов на элемент
При использовании типа d для байтовой строки (по умолчанию для Py2) переход составляет 12, 2 * 6.
bytestring более компактен, но обратите внимание на дисплей:
In [31]: np.array(['smile','smile1'],'S6')
Out[31]: array([b'smile', b'smile1'], dtype='|S6')
Для объекта dtype:
In [32]: sys.getsizeof(np.array(['smile','smile1'],object))
Out[32]: 112
Это 16 байтов - 2 * 8
Но добавьте к этому размер строк Python, дополнительные 133 байта
In [33]: sys.getsizeof('smile')
Out[33]: 78
In [34]: sys.getsizeof('smile1')
Out[34]: 55
и для строк байтов:
In [36]: sys.getsizeof(b'smile')
Out[36]: 38
In [37]: sys.getsizeof(b'smile1')
Out[37]: 39
Обратите внимание, что когда я добавляю символ байта, размер увеличивается на 1. Но когда я добавляю символ юникода, размер фактически уменьшается. Размер юникодных строк сложнее предсказать. Я думаю, что он может выделять до 4 байтов на символ, но фактическое число зависит от символа и кодировки. Обычно мы не пытаемся микроуправлять обработкой строк в Python. (Кроме того, я считаю, что в Python есть какой-то строковый кеш.)
Но когда вы назначаете
X[ind1] = 'smile'
X[ind2] = 'smile2'
в случае объекта вы создаете две строки Python и назначаете ссылки (указатели) на массив. Таким образом, используется память массива (1000 ... * 8 байтов) плюс 133 байта для этих двух строк.
В случае «U6» каждый элемент занимает 4 * 6 байтов, независимо от того, является ли он «smile» или «smile1» (или «s»). Каждый элемент массива использует одно и то же пространство независимо от того, нужен ли он всем для представления строки или нет.
Обычно строки не имеют numpy
силы. Использование памяти типа 'U' или 'S' в порядке, когда строки имеют одинаковый размер, но менее оптимально, если строки различаются по длине, повторяются и / или имеют юникод. numpy
не выполняет большую часть собственной обработки строк. Функции np.char
являются лишь тонкими обертками строковых методов Python.
pandas
решил использовать object
dtype вместо строки dtypes.