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

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

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

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

Я так понимаю, что 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, и того, как бы я применил его, например, для изменения значений (или подмножества значений). в кадре данных, которые удовлетворяют конкретному запросу.

Ответ 1

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

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

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

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

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

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

Ваш пример chained indexing

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

не гарантированно работать (и, таким образом, вы никогда не будете делать это).

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

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

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

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