2016-11-14 4 views
0

рассмотрит ряд панда sКак я могу «разрезать» на два значения?

n = 1000 
s = pd.Series([0] * n + [1] * n, dtype=int) 

s.memory_usage() 

8080 

Я "sparsify" это с помощью to_sparse

s.to_sparse(fill_value=0).memory_usage() 

4080 

Но у меня есть только 2 вида целых чисел. Я бы подумал, что я мог бы дважды разрезать. Есть ли способ сделать это?

+1

Я не знаю, как 'pd' разреженных хранит свои данные. Я угадываю из этих чисел, что он собирает индексы всех 1-х. Матрица 'scipy.sparse' будет хранить как индексы, так и данные (все 1s). В scipy-версии должна быть 1% -ная разрешающая способность, чтобы видеть много преимуществ в памяти и скорости вычислений. – hpaulj

+2

как насчет 's.astype (np.uint8) .to_sparse()'? – MaxU

+0

@MaxU, который определенно снижает объем памяти. Но он мог бы отбросить его еще больше, если бы он отслеживал только позиции нулей и единиц. – piRSquared

ответ

3

Поскольку вы помечено это с scipy, я покажу вам, что scipy.sparse матрица подобна:

In [31]: n=100 
In [32]: arr=np.array([[0]*n+[1]*n],int) 
In [33]: M=sparse.csr_matrix(arr) 
In [34]: M.data 
Out[34]: 
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
     1, 1, 1, 1, 1, 1, 1, 1], dtype=int32) 
In [35]: M.indices 
Out[35]: 
array([100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 
     113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 
     126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 
     139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 
     152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 
     165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 
     178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 
     191, 192, 193, 194, 195, 196, 197, 198, 199], dtype=int32) 
In [36]: M.indptr 
Out[36]: array([ 0, 100], dtype=int32) 

Он заменил n элементы arr с 2 массивов каждый с n/2 элементами. Даже если я заменил int на uint8, массив M.indices по-прежнему будет int32.

Тот факт, что ваша версия pandas имеет половину использования памяти, предполагает, что она просто хранит индексы, а некоторые из них отмечают, что часть data - это все 1 с. Но это всего лишь предположение.

Насколько велика вероятность расслоения?

====================

http://pandas.pydata.org/pandas-docs/stable/sparse.html

Этот пример выглядит панд реализует какое-то сжатие 'Run':

In [4]: sts 
Out[4]: 
0 0.469112 
1 -0.282863 
2   NaN 
3   NaN 
4   NaN 
5   NaN 
6   NaN 
7   NaN 
8 -0.861849 
9 -2.104569 
dtype: float64 
BlockIndex 
Block locations: array([0, 8], dtype=int32) 
Block lengths: array([2, 2], dtype=int32) 

Он определил 2 блока длиной 2 каждый. Он по-прежнему должен хранить 4 значения без заполнения в каком-либо массиве.

КСО разреженный эквивалент (для массива строк):

In [1052]: arr=np.random.rand(10) 
In [1053]: arr[2:-2]=0 
In [1055]: M=sparse.csr_matrix(arr) 
In [1056]: M 
Out[1056]: 
<1x10 sparse matrix of type '<class 'numpy.float64'>' 
    with 4 stored elements in Compressed Sparse Row format> 
In [1057]: M.data 
Out[1057]: array([ 0.37875012, 0.73703368, 0.7935645 , 0.22948213]) 
In [1058]: M.indices 
Out[1058]: array([0, 1, 8, 9], dtype=int32) 
In [1059]: M.indptr 
Out[1059]: array([0, 4], dtype=int32) 

версия панды может быть более компактной, если значения заполнения происходит в блоках. Но я подозреваю, что

0   1.0 
1   1.0 
2   NaN 
3   NaN 
4   NaN 
5   NaN 
6   NaN 
7   NaN 
8   1.0 
9   1.0 

будет производить те же блоки. Я не вижу доказательств того, что он пытается идентифицировать одинаковые значения 1.0 и хранить их как значение плюс счет.

================

основа @MaxU ответа ваш DS хранит 1000 1's, и две отдельных массивы элементов, которые говорят ему, где эти значения сохраняются.

In [56]: sp.memory_usage() 
Out[56]: 1080 

In [57]: sp.sp_index 
Out[57]: 
BlockIndex 
Block locations: array([1000]) 
Block lengths: array([1000]) 

Как долго nonfill значения встречаются в больших тиражах, то block массивов будут малы. Но если рассеянное эти 1000 значений путем из серии, вы бы умножить число блоков по существу

block locations: array([1,3,6,10,...]) 
block lengths: array([1,1,1,2,1,...]) 

Я могу представить себе отображение между csr макетом и пандами блоками, но не проработаны деталями.Макет csr предназначен для работы с 2d-массивами с четкой концепцией строк и столбцов. Похож на то, что разреженный фреймворк содержит только редкие объекты серии.

===================

https://stackoverflow.com/a/38157234/901925 показывает, как отобразить из разреженных значений dataframe к SciPy разреженной матрицей. Для каждого столбца (серия данных) используется sp_values, fill_value, sp_index.

pandas/pandas/sparse/scipy_sparse.py есть код для взаимодействия между scipy разреженными и рядами данных.

===================

kind='integer' produces sparse structure more like scipy.sparse`:

In [62]: n=5; s=pd.Series([0]*5+[1]*5, dtype=int) 
In [63]: ss=s.to_sparse(fill_value=0, kind='integer') 
In [64]: ss 
Out[64]: 
0 0 
1 0 
2 0 
3 0 
4 0 
5 1 
6 1 
7 1 
8 1 
9 1 
dtype: int32 
IntIndex 
Indices: array([5, 6, 7, 8, 9]) 

контраст, который с по умолчанию block:

dtype: int32 
BlockIndex 
Block locations: array([5]) 
Block lengths: array([5]) 

И эквивалентная колонка разреженная матрица может быть построена с:

In [89]: data=ss.values 
In [90]: data=ss.sp_values 
In [91]: rows=ss.sp_index.indices 
In [92]: cols=np.zeros_like(rows) 
In [93]: sparse.csr_matrix((data,(rows,cols))) 
Out[93]: 
<10x1 sparse matrix of type '<class 'numpy.int32'>' 
    with 5 stored elements in Compressed Sparse Row format> 

Существует метод to_coo, но он работает только с более сложным объектом pd.MultiIndex (почему?).

+0

Я пометил его scipy по этой причине. Всегда учусь ;-) – piRSquared

+0

Меня меньше интересует реальная мера расселения, а скорее идеи, стоящие за ней. Я должен буду вернуться к пандам и испортить упорядоченную природу нулей и тех, кто увидит, какие другие идеи я могу почерпнуть. Thx – piRSquared

+1

Для того, что стоит, модуль 'scipy.sparse' был смоделирован по малому внедрению MATLAB, а другая работа с разреженной линейной алгеброй. Таким образом, такие форматы, как 'csr', оптимизированы для таких вещей, как матричный продукт и решения с большими линейными уравнениями. например большие конечные разностные и конечные элементы. – hpaulj

3

Pandas documentation говорит:

В настоящее время float64, int64 и bool dtypes поддерживаются.

так давайте попробуем преобразовать серию в bool значение:

In [53]: s.memory_usage() 
Out[53]: 8080 

In [54]: s.to_sparse().memory_usage() 
Out[54]: 4080 

In [55]: sp = s.astype(bool).to_sparse() 

In [56]: sp.memory_usage() 
Out[56]: 1080 

In [57]: sp.sp_index 
Out[57]: 
BlockIndex 
Block locations: array([1000]) 
Block lengths: array([1000]) 
+0

bool cast - это ключ ... спасибо – Boud

+0

@Boud, спасибо! Но взгляните на [@ hpaulj's solution] (http://stackoverflow.com/a/40595971/5741205), он берет только 56 байт против 1080 за одни и те же данные! – MaxU