Избиране: [], loc и iloc
Накратко: В pandas [] избира колони, loc избира редове и клетки по етикет, а iloc по позиция.
Проблем
„Сиренето поскъпва“
Доставчикът вдига цената на сиренето от 7,90 € на 8,40 €. Управителят иска три неща:
- малка таблица за щанда само с име и цена;
- цената и наличността на един продукт, без да търси с очи;
- новата цена да е в таблицата, а не в някое копие встрани.
Това е избиране: да вземеш част от таблицата, колони, редове или една клетка, и понякога да я промениш. pandas има за това три инструмента: [], loc и iloc.
Идеята
Колони: []
С [] вече взимаш една колона. Ако в скобите сложиш списък с имена, получаваш таблица с тези колони, в този ред:
Едно име дава Series с форма (25,). Списък дава DataFrame с форма (25, 2), дори списъкът да е с една колона: products[['price']] е таблица. Двойните скоби не са специален синтаксис: външните са на избирането, а вътрешните са на списъка.
Идеята
По етикет: loc
loc избира по етикети: първо редовете, после колоните, разделени със запетая. С имената в индекса това е „ред Сирене, колона price“:
- Ред и колона дават една клетка: 7.9.
- Само ред дава целия ред като Series. Етикетите вече са имената на колоните.
- Списъци дават таблица: сиренето и маслото с цена и наличност.
Виж го
Срезът с loc взима и края
Срез с двоеточие (start:stop) работи и в loc, но има разлика, която обърква всички:
loc[0:3] дава 4 имена: от етикет 0 до етикет 3 включително. Срез на позиции (iloc, списъците в Python) спира преди края и дава 3.
Причината е етикетите. С имена в индекса loc['Прясно мляко':'Масло'] дава млечните, от млякото до маслото. Никой не би искал маслото да липсва, само защото е написано последно. Как би написал „до след маслото“?
Идеята
По място: iloc
iloc избира по позиция, като масив на NumPy: първият ред е 0, последният е -1. Етикетите не играят роля:
iloc[0, 1] е първият ред, втората колона: „Бял хляб“. iloc[-1, 1] е последният продукт: подаръчната карта. iloc[:3, [1, 3]] е първите три реда, колоните на място 1 и 3.
Кое кога? loc, когато знаеш какво търсиш: продукт, колона по име. iloc, когато те интересува мястото: първите 5, последния ред. Позициите се местят, щом таблицата се подреди или изреже, а етикетите остават.
Пробвай
Кафето на склада
Кафето е продуктът с id 17. Колко пакета има на склада? Сложи id в индекса (by_id) и запиши в coffee_stock наличността като едно число.
Решение
import pandas as pd
products = pd.read_csv('products.csv')
by_id = products.set_index('id')
coffee_stock = by_id.loc[17, 'stock']
print(coffee_stock)by_id = products.set_index('id') и coffee_stock = by_id.loc[17, 'stock'] дава 15. Капанът е products.loc[17, 'stock']: без set_index етикетите са номерата от 0, етикет 17 е 18-ият ред, чаят от мента, и отговорът е 33. Без колоната (by_id.loc[17]) получаваш целия ред, а не числото.
Идеята
Копие или същата таблица
Сега новата цена. Изрязваш млечните и сменяш цената на сиренето в тях. Променя ли се products?
Не: в 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, но не е:
Цената е пак 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 броя:
empty.sum() брои изчерпаните: 2. След реда с loc баницата и краставиците имат по 30. Маските върху таблица ще ползваме много в следващия урок за филтрите.
Пробвай
Доставка за почти празните
Всеки продукт с по-малко от 10 бройки на склада получава още 20. Запиши в low маската, а после промени наличността им в products.
Решение
import pandas as pd
products = pd.read_csv('products.csv')
low = products['stock'] < 10
products.loc[low, 'stock'] = products.loc[low, 'stock'] + 20
print(products.loc[low, ['name', 'stock']])low = products['stock'] < 10 хваща 4 продукта, а products.loc[low, 'stock'] = products.loc[low, 'stock'] + 20 ги допълва: баницата и краставиците стават 20, тиганът 28, а ножовете 25. Ако изрежеш short = products.loc[low] и смениш в него, products остава същата. Веригата products['stock'][low] = … също не пише в таблицата.
Упражнение
Таблицата за щанда
Имената са в индекса на by_name. Смени цената на сиренето на 8.4 в by_name. После запиши в counter таблицата за щанда: млечните от Прясно мляко до Масло, с колоните price и stock.
Решение
import pandas as pd
products = pd.read_csv('products.csv')
by_name = products.set_index('name')
by_name.loc['Сирене', 'price'] = 8.4
counter = by_name.loc['Прясно мляко':'Масло', ['price', 'stock']]
counterby_name.loc['Сирене', 'price'] = 8.4 пише в таблицата. counter = by_name.loc['Прясно мляко':'Масло', ['price', 'stock']] дава 5 реда с маслото, защото loc взима края. Със iloc[4:8] маслото липсва. Ако смениш цената в counter или с by_name['price']['Сирене'], щандът и складът показват различни цени, а by_name остава със старата.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Първата таблица · Векторизация · Series и DataFrame
- Продължава в: Филтри и подреждане · Нови колони · Типове и липсващи стойности · Групи: groupby
- Задачи по темата: Таблици с pandas