Які правила Pandas використовує для створення перегляду та копії?


118

Мене бентежить правила, які 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

не матиме ніякого впливу на оригінальний dataframe, 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']

так як це швидше і завжди буде працювати

Ланцюгова індексація - це дві окремі операції пітона, і тому пандами неможливо надійно перехопити (ви часто отримуєте SettingWithCopyWarning, але це теж не на 100% виявляється). У Dev документи , які ви вказали, пропонують набагато більш повне пояснення.


3
.queryЗАВЖДИ поверне копію через те, що вона робить (а не перегляд), тому що її оцінюють n numexpr. Тож я додам це до 'правил'
Джефф

3
pandas покладається на numpy, щоб визначити, чи створюється подання. У випадку одного типу типу (який може бути 1-d для серії, 2-d для кадру тощо). numpy може генерувати представлення; це залежить від того, що ви нарізаєте; іноді ви можете отримати огляд, а іноді не можете. панди взагалі не покладаються на цей факт, оскільки не завжди очевидно, чи генерується погляд. але це не має значення, оскільки локальний не покладається на це під час налаштування. Однак при індексації ланцюгів це дуже важливо (і, отже, чому ланцюгова індексація погана)
Джефф

3
Дуже дякую Джеффу, ваша відповідь є найкориснішою. Яке джерело / посилання на цю тему?
Каміксаве

4
Тоді спочатку дякую за вашу чудову роботу! По-друге, якщо у вас є достатньо часу, я думаю, було б чудово додати абзац, подібний до вашої основної відповіді в документі.
Каміксаве

2
Безумовно, потрібно взяти запит на додавання / перегляд документів. действуй.
Джефф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.