Към съдържанието
wannacode

Избиране: [], loc и iloc

Накратко: В pandas [] избира колони, loc избира редове и клетки по етикет, а iloc по позиция.

Проблем

„Сиренето поскъпва“

Доставчикът вдига цената на сиренето от 7,90 € на 8,40 €. Управителят иска три неща:

  • малка таблица за щанда само с име и цена;
  • цената и наличността на един продукт, без да търси с очи;
  • новата цена да е в таблицата, а не в някое копие встрани.

Това е избиране: да вземеш част от таблицата, колони, редове или една клетка, и понякога да я промениш. pandas има за това три инструмента: [], loc и iloc.

Идеята

Колони: []

С [] вече взимаш една колона. Ако в скобите сложиш списък с имена, получаваш таблица с тези колони, в този ред:

Pythonданни: таблиците на магазина

Едно име дава Series с форма (25,). Списък дава DataFrame с форма (25, 2), дори списъкът да е с една колона: products[['price']] е таблица. Двойните скоби не са специален синтаксис: външните са на избирането, а вътрешните са на списъка.

Идеята

По етикет: loc

loc избира по етикети: първо редовете, после колоните, разделени със запетая. С имената в индекса това е „ред Сирене, колона price“:

Pythonданни: таблиците на магазина
  • Ред и колона дават една клетка: 7.9.
  • Само ред дава целия ред като Series. Етикетите вече са имената на колоните.
  • Списъци дават таблица: сиренето и маслото с цена и наличност.

Виж го

Срезът с loc взима и края

Срез с двоеточие (start:stop) работи и в loc, но има разлика, която обърква всички:

Pythonданни: таблиците на магазина

loc[0:3] дава 4 имена: от етикет 0 до етикет 3 включително. Срез на позиции (iloc, списъците в Python) спира преди края и дава 3.

Причината е етикетите. С имена в индекса loc['Прясно мляко':'Масло'] дава млечните, от млякото до маслото. Никой не би искал маслото да липсва, само защото е написано последно. Как би написал „до след маслото“?

Идеята

По място: iloc

iloc избира по позиция, като масив на NumPy: първият ред е 0, последният е -1. Етикетите не играят роля:

Pythonданни: таблиците на магазина

iloc[0, 1] е първият ред, втората колона: „Бял хляб“. iloc[-1, 1] е последният продукт: подаръчната карта. iloc[:3, [1, 3]] е първите три реда, колоните на място 1 и 3.

Кое кога? loc, когато знаеш какво търсиш: продукт, колона по име. iloc, когато те интересува мястото: първите 5, последния ред. Позициите се местят, щом таблицата се подреди или изреже, а етикетите остават.

1. Индексът е по подразбиране (0, 1, 2…). Колко реда дават products.loc[2:5] и products.iloc[2:5]?

Пробвай

Кафето на склада

Кафето е продуктът с id 17. Колко пакета има на склада? Сложи id в индекса (by_id) и запиши в coffee_stock наличността като едно число.

Pythonданни: таблиците на магазина

Идеята

Копие или същата таблица

Сега новата цена. Изрязваш млечните и сменяш цената на сиренето в тях. Променя ли се products?

Pythonданни: таблиците на магазина

Не: в dairy сиренето е 8.4, а в products е още 7.9. В pandas 3 всяко изрязано парче се държи като копие. Промяната на парчето не пипа оригинала. Това се казва Copy-on-Write: pandas не копира данните веднага, а чак когато някой от двата обекта се промени.

За да промениш таблицата, пишеш в самата нея, с loc и с реда и колоната наведнъж: products.loc[6, 'price'] = 8.4.

Виж го

Две скоби подред не пишат

Изкушението е products['price'][6] = 8.4: колоната, после клетката. Изглежда като loc, но не е:

Pythonданни: таблиците на магазина

Цената е пак 7.9. products['price'] е отделен обект, копие, и [6] = 8.4 пише в него. Това се казва верижно присвояване (chained assignment). pandas 3 никога не го изпълнява върху таблицата и показва предупреждение ChainedAssignmentError с подсказка за .loc.

Правилото е едно: пишеш с едно loc[ред, колона] = … върху таблицата, която искаш да промениш.

По-точно, за любопитните

В pandas 1 и 2 същият код понякога променяше таблицата, а понякога не, според това дали отдолу има копие или изглед. Затова имаше предупреждение SettingWithCopyWarning, което казваше „може би“. Ще го срещнеш в стари статии и в отговори из интернет. В pandas 3 (2026) правилото е ясно, а предупреждението е история. Ако кодът ти трябва да върви и на стара версия, loc наведнъж е вярно и там.

Идеята

Много редове наведнъж: маска в loc

На мястото на реда в loc може да стои маска: колона от True и False, както маските в NumPy. Тогава промяната е за всички редове, където маската е True. Два продукта са изчерпани и пристига доставка по 30 броя:

Pythonданни: таблиците на магазина

empty.sum() брои изчерпаните: 2. След реда с loc баницата и краставиците имат по 30. Маските върху таблица ще ползваме много в следващия урок за филтрите.

Пробвай

Доставка за почти празните

Всеки продукт с по-малко от 10 бройки на склада получава още 20. Запиши в low маската, а после промени наличността им в products.

Pythonданни: таблиците на магазина

Упражнение

Таблицата за щанда

Имената са в индекса на by_name. Смени цената на сиренето на 8.4 в by_name. После запиши в counter таблицата за щанда: млечните от Прясно мляко до Масло, с колоните price и stock.

Pythonданни: таблиците на магазина

Тест

Провери се

1. Кое връща таблица (DataFrame) с колоните name и price?
2. Индексът са имената на продуктите. Какво дава by_name.loc['Сирене', 'price']?
3. products.loc[17, 'stock'] дава 33, а кафето (id 17) има 15 пакета. Защо?
4. В pandas 3: short = products.loc[low], после short['stock'] = 30. Какво става с products?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·