Проверка, является ли фрейм данных копированием или просмотром в Pandas
Есть ли простой способ проверить, являются ли два фрейма данных разными копиями или представлениями одних и тех же базовых данных, которые не связаны с манипуляциями? Я пытаюсь понять, когда каждый из них генерируется, и с учетом того, насколько необычными кажутся правила, я бы хотел простой способ проверить.
Например, я думал, что "id(df.values)" будет стабильным во всех представлениях, но они, похоже, не являются:
# Make two data frames that are views of same data.
df = pd.DataFrame([[1,2,3,4],[5,6,7,8]], index = ['row1','row2'],
columns = ['a','b','c','d'])
df2 = df.iloc[0:2,:]
# Demonstrate they are views:
df.iloc[0,0] = 99
df2.iloc[0,0]
Out[70]: 99
# Now try and compare the id on values attribute
# Different despite being views!
id(df.values)
Out[71]: 4753564496
id(df2.values)
Out[72]: 4753603728
# And we can of course compare df and df2
df is df2
Out[73]: False
Другие ответы, которые я искал, которые пытаются дать правила, но не кажутся последовательными, а также не отвечают на этот вопрос о том, как тестировать:
Какие правила использует Pandas для создания представления против копии?
Панды: субиндексация фреймов данных: копии против представлений
И конечно: - http://pandas.pydata.org/pandas-docs/stable/indexing.html
ОБНОВЛЕНИЕ: комментарии ниже, кажется, отвечают на вопрос - глядя на df.values.base
атрибут, а не df.values
Атрибут делает это, как и ссылка на df._is_copy
атрибут (хотя последний, вероятно, очень плохая форма, так как это внутренний).
2 ответа
Ответы от HYRY и Marius в комментариях!
Можно проверить либо:
проверка эквивалентности
values.base
атрибут, а неvalues
атрибут, как в:df.values.base is df2.values.base
вместоdf.values is df2.values
,- или используя (по общему признанию)
_is_view
атрибут (df2._is_view
являетсяTrue
).
Спасибо всем!
Я разработал этот пример с помощью pandas 1.0.1. Есть не только логическое значение_is_view
атрибут, но также _is_copy
который может быть None
или ссылка на исходный DataFrame:
df = pd.DataFrame([[1,2,3,4],[5,6,7,8]], index = ['row1','row2'],
columns = ['a','b','c','d'])
df2 = df.iloc[0:2, :]
df3 = df.loc[df['a'] == 1, :]
# df is neither copy nor view
df._is_view, df._is_copy
Out[1]: (False, None)
# df2 is a view AND a copy
df2._is_view, df2._is_copy
Out[2]: (True, <weakref at 0x00000236635C2228; to 'DataFrame' at 0x00000236635DAA58>)
# df3 is not a view, but a copy
df3._is_view, df3._is_copy
Out[3]: (False, <weakref at 0x00000236635C2228; to 'DataFrame' at 0x00000236635DAA58>)
Таким образом, проверка этих двух атрибутов должна сказать вам не только о том, имеете ли вы дело с представлением или нет, но также и о том, есть ли у вас копия или "исходный" DataFrame.
См. Также эту ветку для обсуждения, объясняющего, почему вы не всегда можете предсказать, вернет ли ваш код представление или нет.
Вы могли бы проследить, сколько памяти использует ваша среда pandas / python, и, исходя из предположения, что копия будет использовать больше памяти, чем представление, сможете решить так или иначе.
Я полагаю, что есть библиотеки, которые будут представлять использование памяти в самой среде Python - например, Heapy/Guppy.
Должна быть метрика, которую вы можете применить, которая дает базовое представление об использовании памяти до создания проверяемого объекта, а затем еще одно изображение. Сравнение двух карт памяти (при условии, что больше ничего не было создано, и мы можем выделить изменения из-за нового объекта), должно дать представление о том, было ли создано представление или копия.
Нам необходимо получить представление о различных профилях памяти для каждого типа реализации, но некоторые эксперименты должны дать результаты.