Какие правила использует Pandas для создания представления или копии?

119

Я смущен правилами, которые использует Pandas, когда решает, что выбор из фрейма данных является копией исходного фрейма данных или представлением оригинала.

Если у меня, например,

df = pd.DataFrame(np.random.randn(8,8), columns=list('ABCDEFGH'), index=range(1,9))

Я понимаю, что a queryвозвращает копию, поэтому что-то вроде

foo = df.query('2 < index <= 5')
foo.loc[:,'E'] = 40

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

df.iloc[3] = 70

или

df.ix[1,'B':'E'] = 222

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

df[df.C <= df.B] = 7654321

меняется df, но

df[df.C <= df.B].ix[:,'B':'E']

не.

Есть ли простое правило, которое использует Pandas, которого мне просто не хватает? Что происходит в этих конкретных случаях; и, в частности, как мне изменить все значения (или подмножество значений) в фрейме данных, удовлетворяющем конкретному запросу (как я пытаюсь сделать в последнем примере выше)?


Примечание. Это не то же самое, что этот вопрос ; и я прочитал документацию , но не осведомлен о ней. Я также прочитал «Связанные» вопросы по этой теме, но мне все еще не хватает простого правила, которое использует Pandas, и того, как его применить, например, к изменению значений (или подмножества значений) в кадре данных, который удовлетворяет конкретному запросу.

Оромэ
источник

Ответы:

138

Вот правила, последующее переопределение:

  • Все операции генерируют копию

  • Если inplace=Trueпредоставляется, он будет изменен на месте; только некоторые операции поддерживают это

  • Индексатор, который устанавливает, например .loc/.iloc/.iat/.at, установит на место.

  • Индексатор, который попадает на объект с одним типом, почти всегда является представлением (в зависимости от макета памяти это может быть не так, поэтому это ненадежно). Это в основном для эффективности. (приведенный выше пример предназначен для .query; это всегда будет возвращать копию в том виде, в котором она была оценена numexpr)

  • Индексатор, который получает объект с несколькими типами, всегда является копией.

Ваш пример chained indexing

df[df.C <= df.B].loc[:,'B':'E']

не гарантируется работа (и поэтому вы никогда не должны этого делать).

Вместо этого сделайте:

df.loc[df.C <= df.B, 'B':'E']

так как это быстрее и всегда будет работать

Цепная индексация - это 2 отдельные операции Python, и поэтому pandas не может надежно ее перехватить (вы часто получаете a SettingWithCopyWarning, но это также не обнаруживается на 100%). Документы разработчиков , на которые вы указали, предлагают гораздо более полное объяснение.

Джефф
источник
3
.queryВСЕГДА будет возвращать копию из-за того, что она делает (а не из представления), потому что она оценивается n numexpr. Так что я добавлю это к «правилам»
Джефф
3
pandas полагается на numpy, чтобы определить, создается ли представление. В одном случае dtype (который может быть 1-м для серии, 2-м для кадра и т. Д.). numpy может генерировать представление; это зависит от того, что вы нарезаете; иногда можно увидеть, а иногда нет. pandas вообще не полагается на этот факт, поскольку не всегда очевидно, создается ли представление. но это не имеет значения, поскольку loc не полагается на это при настройке. Однако при цепной индексации это очень важно (и, следовательно, почему цепная индексация плохая)
Джефф
3
Большое спасибо Джеффу, твой ответ очень полезен. Какой у вас источник / ссылка по этой теме?
Kamixave
4
Тогда прежде всего спасибо за вашу отличную работу! Во-вторых, если у вас есть достаточно времени, я думаю, было бы здорово добавить абзац, аналогичный вашему основному ответу в документе.
Kamixave
2
конечно, потребуется запрос на добавление / изменение документов. Действуй.
Джефф