2013-08-18 4 views
2

Я хочу объединить два панда DataFrames без копирования данных. То есть, я хочу, чтобы конкатенированный DataFrame представлял собой представление данных в двух исходных DataFrames. Я попытался использовать concat(), и это не сработало. Этот блок кода показывает, что изменение базовых данных влияет на два DataFrames, которые объединяются, но не сцепляются DataFrame:Как скомпилировать pandas DataFrames без копирования данных?

arr = np.random.randn(12).reshape(6, 2) 
df = pd.DataFrame(arr, columns = ('VALE5', 'PETR4'), index = dates) 
arr2 = np.random.randn(12).reshape(6, 2) 
df2 = pd.DataFrame(arr, columns = ('AMBV3', 'BBDC4'), index = dates) 
df_concat = pd.concat(dict(A = df, B = df2),axis=1) 
pp(df) 
pp(df_concat) 
arr[0, 0] = 9999999.99 
pp(df) 
pp(df_concat) 

Это выход из последних пяти строк. df изменилось после того, как новое значение было присвоено arr [0, 0]; df_concat не повлиял.

In [56]: pp(df) 
      VALE5  PETR4 
2013-01-01 -0.557180 0.170073 
2013-01-02 -0.975797 0.763136 
2013-01-03 -0.913254 1.042521 
2013-01-04 -1.973013 -2.069460 
2013-01-05 -1.259005 1.448442 
2013-01-06 -0.323640 0.024857 

In [57]: pp(df_concat) 
       A     B   
      VALE5  PETR4  AMBV3  BBDC4 
2013-01-01 -0.557180 0.170073 -0.557180 0.170073 
2013-01-02 -0.975797 0.763136 -0.975797 0.763136 
2013-01-03 -0.913254 1.042521 -0.913254 1.042521 
2013-01-04 -1.973013 -2.069460 -1.973013 -2.069460 
2013-01-05 -1.259005 1.448442 -1.259005 1.448442 
2013-01-06 -0.323640 0.024857 -0.323640 0.024857 

In [58]: arr[0, 0] = 9999999.99 

In [59]: pp(df) 
       VALE5  PETR4 
2013-01-01 9999999.990000 0.170073 
2013-01-02  -0.975797 0.763136 
2013-01-03  -0.913254 1.042521 
2013-01-04  -1.973013 -2.069460 
2013-01-05  -1.259005 1.448442 
2013-01-06  -0.323640 0.024857 

In [60]: pp(df_concat) 
       A     B   
      VALE5  PETR4  AMBV3  BBDC4 
2013-01-01 -0.557180 0.170073 -0.557180 0.170073 
2013-01-02 -0.975797 0.763136 -0.975797 0.763136 
2013-01-03 -0.913254 1.042521 -0.913254 1.042521 
2013-01-04 -1.973013 -2.069460 -1.973013 -2.069460 
2013-01-05 -1.259005 1.448442 -1.259005 1.448442 
2013-01-06 -0.323640 0.024857 -0.323640 0.024857 

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

Кроме того, есть ли быстрый способ проверить, связаны ли два DataFrames с одними и теми же базовыми данными? (если не удастся изменить данные и проверить, изменился ли каждый DataFrame)

Спасибо за помощь.

FS

+0

В настоящее время лучший способ проверить наличие двух массивов памяти numpy здесь: http://stackoverflow.com/questions/10747748/how-do-i-check-that-two-slices-of-numpy- array-are-the-same-or-overlapping –

ответ

1

Вы не можете (по крайней мере легко). Когда вы вызываете concat, в конечном итоге вызывается np.concatenate.

См. this answer explaining why you can't concatenate arrays without copying. Короче, это то, что массивы не гарантированно смежны в памяти.

Вот простой пример

a = rand(2, 10) 
x, y = a 
z = vstack((x, y)) 
print 'x.base is a and y.base is a ==', x.base is a and y.base is a 
print 'x.base is z or y.base is z ==', x.base is z or y.base is z 

Выход:

x.base is a and y.base is a == True 
x.base is z or y.base is z == False 

Даже если x и y одни и те же base, а именно a, concatenate (и, таким образом, vstack) не может предположить, что они делают, так как один часто хочет конкатенировать произвольно перечеркнутые массивы.

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

a = arange(10) 
b = a[::2] 
print a.strides 
print b.strides 

Выход:

(8,) 
(16,) 

Это почему происходит следующее:

In [214]: a = arange(10) 

In [215]: a[::2].view(int16) 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-215-0366fadb1128> in <module>() 
----> 1 a[::2].view(int16) 

ValueError: new type not compatible with array. 

In [216]: a[::2].copy().view(int16) 
Out[216]: array([0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 8, 0, 0, 0], dtype=int16) 

EDIT: Использование pd.merge(df1, df2, copy=False) (или df1.merge(df2, copy=False)), когда df1.dtype != df2.dtype не сделает копию. В противном случае делается копия.

+0

Это ошибка? 'merge' имеет параметр' copy', поэтому, когда я делаю 'df_concat = df.merge (df1, left_index = True, right_index = True, copy = False)' Если индексы обоих DataFrames одинаковы (что в этом случае true, объекты Series не нужно изменять, почему pandas копирует данные, когда я явно инструктировал его не с помощью 'copy = False'?Даже если я сначала создаю индекс, а затем создаю 'df',' df' и 'df_concat', а' df.index - 'df_concat.index' возвращает' True', все же данные копируются. –

+0

Я не обязательно думаю, что это ошибка. Сейчас я изучаю это. Однако это должно быть лучше документировано. –

+0

это не ошибка; concatenate всегда копирует. нет никакого способа сохранить представление (конечно, вы можете просто настроить subviews, если хотите, чтобы они соответствовали оригинальным кадрам). что именно вы пытаетесь достичь? – Jeff