कॉलम और पंक्तियाँ चुनना — नाम से या स्थान से
टेबल के किसी हिस्से की ओर इशारा करना: ब्रैकेट्स से कॉलम, loc से लेबल द्वारा और iloc से पोज़ीशन द्वारा पंक्तियाँ, at से एकल सेल — और हमेशा यह जानना कि आप किस तरीके का उपयोग कर रहे हैं।
- 1समस्या
- 2समझें
- 3उदाहरण
- 4अनुमान
- 5स्वयं करें
- 6चुनौती
वह समस्या जिसे हम हल कर रहे हैं
आपने दुकान की ऑर्डर फ़ाइल पढ़ ली है और उसकी जाँच भी कर ली है, जैसा कि अध्याय तीन में सिखाया गया था। अब लोग आपसे इसके बारे में सवाल पूछने लगे हैं।
स्टॉक टीम कहती है: "हमें हर ऑर्डर का बस प्रोडक्ट और क्वांटिटी (संख्या) भेज दीजिए — और कुछ नहीं।" अकाउंटेंट कहते हैं: "ऑर्डर 1006 वास्तव में क्या था, और उसकी कीमत क्या थी?" और आपके मैनेजर कहते हैं: "मुझे वो आखिरी तीन ऑर्डर दिखाओ जो आए थे।"
इनमें से कोई भी पूरी टेबल पर की जाने वाली गणना नहीं है। इनमें से प्रत्येक सवाल इशारा करने (pointing) के बारे में है: कुछ कॉलमों की ओर, एक पंक्ति की ओर, आखिरी कुछ पंक्तियों की ओर, या किसी एक सेल की ओर। आठ पंक्तियों के लिए पूरी टेबल प्रिंट करके उंगली रखकर पढ़ना काम कर जाता है। लेकिन आठ हज़ार पंक्तियों के लिए यह काम नहीं करता, और प्रोग्राम के अंदर तो बिल्कुल नहीं करता, क्योंकि प्रोग्राम की कोई उंगली नहीं होती।
पांडास में किसी चीज़ की ओर इशारा करने के कई तरीके हैं, और कई तरीके होने का कारण ही इस अध्याय का असली विषय है। किसी पंक्ति की ओर दो अलग-अलग तरीकों से इशारा किया जा सकता है: उसके नाम से (इंडेक्स में उसका लेबल) या उसकी पोज़ीशन (स्थान) से (पहली, दूसरी, आखिरी)। जब कोई टेबल ताज़ा पढ़ी जाती है, तो ये दोनों संयोग से एक ही संख्याएँ होती हैं, इसलिए शुरुआती लोग कभी ध्यान ही नहीं देते कि ये दो अलग चीज़ें हैं। जिस पल आप आखिरी तीन पंक्तियाँ चुनते हैं, या सॉर्ट करते हैं, या फ़िल्टर करते हैं, वे दोनों एक समान रहना बंद हो जाते हैं — और जो कोड इन दोनों को आपस में मिला देता है, वह बिना किसी एरर के चुपचाप गलत पंक्ति लौटाने लगता है।
इसलिए यह अध्याय डेटा चुनने (selecting) के बारे में है, लेकिन मुख्य रूप से यह हमेशा यह जानने के बारे में है कि आप इन दोनों में से किसका उपयोग कर रहे हैं।
इस अध्याय के अंत में आप कर पाएंगे
- एक कॉलम चुनकर
Seriesपाना, या कई कॉलम चुनकरDataFrameपाना — और यह जानना कि आपके हाथ में क्या आया है .locसे लेबल द्वारा और.ilocसे पोज़ीशन द्वारा पंक्तियाँ चुनना, और यह समझाना कि उनके स्लाइस अलग तरीके से क्यों समाप्त होते हैं.loc[rows, columns]के साथ पंक्तियों और कॉलमों को एक साथ चुनना और परिणाम के आकार (shape) का पहले से अनुमान लगाना — यहाँ तक कि.locया.atसे एक एकल मान प्राप्त करनाset_index()से पंक्तियों को सार्थक लेबल देना, और देखना कि यह.locके अर्थ को कैसे बदल देता है- यह समझाना कि पांडास 3 में किसी सिलेक्शन को बदलने से मूल टेबल क्यों नहीं बदलती, और मूल टेबल को सही तरीके से बदलना; सिलेक्शन से उत्पन्न होने वाले
KeyErrorऔरIndexErrorसंदेशों को समझना और ठीक करना
ज़रूरी शर्तें: CSV फ़ाइल पढ़ना, और पढ़ने के बाद जांचना।
पहले फ़ाइल बनाएँ
अपने प्रोजेक्ट फ़ोल्डर में ठीक इन नौ पंक्तियों के साथ orders.csv बनाएँ। इस फ़ाइल का उपयोग बाकी के पूरे कोर्स में किया जाएगा, इसलिए इसे ऐसी जगह सहेजें जहाँ आप इसे फिर से ढूँढ सकें:
order_id,date,branch,product,category,quantity,price
1001,2024-03-01,north,pen,stationery,12,15.0
1002,2024-03-01,south,notebook,stationery,5,60.0
1003,2024-03-02,north,bag,accessories,2,850.0
1004,2024-03-02,east,bottle,accessories,7,120.0
1005,2024-03-03,north,eraser,stationery,30,8.0
1006,2024-03-03,south,bag,accessories,1,850.0
1007,2024-03-04,east,pen,stationery,20,15.0
1008,2024-03-04,north,bottle,accessories,4,120.0प्रत्येक पंक्ति एक ऑर्डर है: एक ऑर्डर नंबर, तारीख, दुकान की वह शाखा जिसने इसे बेचा, क्या बेचा गया, उत्पाद की श्रेणी (category), कितनी संख्या, और एक वस्तु की कीमत।
कोड लिखने से पहले
डेटा चुनना इतना छोटा काम लगता है कि लोग तुरंत ब्रैकेट्स टाइप करना शुरू कर देते हैं। पहले इन चरणों पर एक मिनट बिताएँ, क्योंकि इस अध्याय में सिलेक्शन की हर ग़लती इनमें से किसी एक को छोड़ने से ही होती है।
1. प्रश्न को एक वाक्य में कहें, और संज्ञाओं (nouns) को रेखांकित करें। संज्ञाएँ आपको बताती हैं कि आप किस चीज़ की ओर इशारा कर रहे हैं:
- "हर ऑर्डर का product और quantity" — दो कॉलम, सभी पंक्तियाँ
- "order 1006" — एक पंक्ति, उसके ऑर्डर नंबर से पहचानी गई
- "आखिरी तीन ऑर्डर" — पोज़ीशन के अनुसार पंक्तियाँ, अंत से गिनी गईं
- "order 1006 की price" — एक सेल: एक पंक्ति और एक कॉलम एक साथ
2. टेबल में इशारा करने से पहले टेबल को देखें। आप केवल उन्हीं नामों की ओर इशारा कर सकते हैं जो मौजूद हैं। सिलेक्शन के लिए तीन चीज़ें मायने रखती हैं: आकार (size), कॉलमों के सटीक नाम, और इंडेक्स — यानी बाईं ओर के लेबल्स।
import pandas as pd
orders = pd.read_csv("orders.csv")
print(orders.shape)
print(list(orders.columns))
print(orders.index)(8, 7)
['order_id', 'date', 'branch', 'product', 'category', 'quantity', 'price']
RangeIndex(start=0, stop=8, step=1)कॉलम के नाम कोट्स के अंदर एक लिस्ट के रूप में आते हैं — ताकि आप देख सकें कि 'price' छोटे अक्षरों में है और इसमें कोई अतिरिक्त स्पेस नहीं है। इंडेक्स 0 से 7 तक एक RangeIndex है: लेबल्स केवल एक गिनती हैं। इसे याद रखें, क्योंकि यह वही संयोग है जिस पर यह पूरा अध्याय आधारित है। अभी, जिस पंक्ति का लेबल 2 है, वह पंक्ति पोज़ीशन 2 पर भी है। यह हमेशा सच नहीं रहेगा।
3. परिणाम पाने से पहले उसका रूप सोचें (sketch)। बाहर क्या आना चाहिए — एक संख्या, एक कॉलम, या एक छोटी टेबल? कितनी पंक्तियाँ और कितने कॉलम? स्टॉक टीम के अनुरोध का उत्तर 8 पंक्तियों और 2 कॉलमों की एक टेबल है। "order 1006" के लिए यह एक पंक्ति है। "order 1006 की कीमत" के लिए यह एक संख्या, 850.0 है। यदि आप अपने अपेक्षित आकार को जानते हैं, तो परिणाम देखते ही गलत सिलेक्शन तुरंत पकड़ में आ जाता है।
4. अपनी जानकारी के आधार पर टूल चुनें। यह सूची एक ही नज़र में पूरे अध्याय का सार है:
- आपको कॉलम के नाम पता हैं → स्क्वायर ब्रैकेट्स:
orders["quantity"],orders[["product", "quantity"]] - आपको पंक्ति का लेबल पता है, इंडेक्स में उसका नाम →
.loc:orders.loc[2] - आपको पंक्ति की पोज़ीशन पता है — पहली, आखिरी, पाँचवीं →
.iloc:orders.iloc[-3:] - आपको पंक्तियाँ और कॉलम एक साथ चाहिए →
.loc[rows, cols]या.iloc[rows, cols]:orders.loc[2:4, ["product", "price"]] - आपको ठीक एक सेल चाहिए →
.at[row, col]या.loc[row, col]:orders.at[5, "price"]
5. तय करें कि आप कैसे जाँच करेंगे। किसी भी सिलेक्शन के बाद, परिणाम का .shape या type() प्रिंट करें और अपने सोचे हुए आकार से तुलना करें। यह बस एक लाइन का कोड है, और यह नीचे दी गई अधिकांश ग़लतियों को गलत संख्याओं में बदलने से पहले ही पकड़ लेता है।
अध्याय का बाकी हिस्सा इन टूल्स को एक-एक करके समझाता है, प्रत्येक के अपने हल किए गए उदाहरण के साथ।
एक कॉलम: स्क्वायर ब्रैकेट्स में नाम
स्क्वायर ब्रैकेट्स में कॉलम का नाम लिखें और आपको वह कॉलम मिल जाएगा:
quantity = orders["quantity"]
print(type(quantity))
print(quantity)<class 'pandas.Series'>
0 12
1 5
2 2
3 7
4 30
5 1
6 20
7 4
Name: quantity, dtype: int64परिणाम में जो मिलता है वह एक Series है — ठीक वही ऑब्जेक्ट जो अध्याय दो में था: मान (values), बाईं ओर एक इंडेक्स, एक Name (वह कॉलम जिससे यह आया है) और एक dtype। ध्यान दें कि इंडेक्स भी इसके साथ आया है। 0 से 7 कोई सजावट नहीं हैं: वे अभी भी बताते हैं कि प्रत्येक संख्या किस पंक्ति से संबंधित है।
चूँकि यह एक Series है, इसलिए प्रत्येक Series मेथड इस पर सीधे काम करता है:
print(orders["quantity"].sum())81एक कॉलम चुनने का सामान्य कारण यही होता है: उससे कोई सवाल पूछना या गणना करना।
कई कॉलम: ब्रैकेट्स के अंदर एक लिस्ट
स्टॉक टीम के लिए, आपको दो कॉलम चाहिए। ब्रैकेट्स के अंदर नामों की एक लिस्ट रखें:
stock = orders[["product", "quantity"]]
print(type(stock))
print(stock)<class 'pandas.DataFrame'>
product quantity
0 pen 12
1 notebook 5
2 bag 2
3 bottle 7
4 eraser 30
5 bag 1
6 pen 20
7 bottle 4डबल ब्रैकेट्स कोई विशेष सिंटैक्स नहीं हैं, और इसे स्पष्ट रूप से समझना ज़रूरी है। बाहर की जोड़ी सिलेक्शन के लिए है; अंदर की जोड़ी एक साधारण पायथन लिस्ट है, ["product", "quantity"]। आप पहले लिस्ट बना सकते थे और फिर उसे पास कर सकते थे — wanted = ["product", "quantity"] और फिर orders[wanted] — और इसका मतलब बिल्कुल वही होता। कॉलम लिस्ट के क्रम में वापस आते हैं, इसलिए कॉलमों का क्रम बदलने के लिए भी इसी का उपयोग किया जाता है।
परिणाम एक DataFrame है, क्योंकि दो कॉलम वाली टेबल एक टेबल ही होती है। और यहाँ एक ऐसा अंतर है जो लोगों को महीनों तक उलझाए रखता है: एक ऐसी लिस्ट जिसमें केवल एक नाम हो, वह भी DataFrame ही देती है।
print(orders["product"].shape)
print(orders[["product"]].shape)(8,)
(8, 1)(8,) एक Series है — एक आयाम (one dimension), आठ मान। (8, 1) आठ पंक्तियों और एक कॉलम वाला DataFrame है। वे अलग तरह से प्रिंट होते हैं, उनके मेथड्स अलग होते हैं, और जब आप उन्हें किसी फ़ाइल में सहेजते हैं, तो DataFrame अपने कॉलम का हेडर बनाए रखता है। नियम सरल है: एक नाम Series देता है; एक लिस्ट DataFrame देती है — चाहे लिस्ट में कितने भी नाम क्यों न हों।
orders.quantity क्यों नहीं?
आप कई ट्यूटोरियल में डॉट के साथ कॉलम एक्सेस लिखा देखेंगे:
print(orders.branch.head(2))0 north
1 south
Name: branch, dtype: strयह यहाँ काम करता है, और छोटा भी है। लेकिन यह केवल तभी काम करता है जब कॉलम का नाम संयोग से एक वैध पायथन नाम हो जो पहले से किसी अन्य चीज़ के लिए उपयोग न किया गया हो — और एक DataFrame में सैकड़ों मेथड्स और एट्रिब्यूट्स होते हैं। यहाँ एक छोटी टेबल है जिसके कॉलमों के नाम count और size हैं, जो किसी दुकान के लिए पूरी तरह से उचित नाम हैं:
d = pd.DataFrame({"count": [1, 2], "size": [3, 4]})
print(d.size)
print(d["size"])4
0 3
1 4
Name: size, dtype: int64d.size ने आपको कॉलम बिल्कुल नहीं दिया। इसने बिना किसी चेतावनी के DataFrame का अपना size एट्रिब्यूट दे दिया — सेलों की कुल संख्या, 2 × 2 = 4। कोई एरर नहीं, बस एक गलत उत्तर। जिस नाम में स्पेस हो, जैसे unit price, उसे तो डॉट के साथ लिखा ही नहीं जा सकता। ब्रैकेट्स में इनमें से कोई समस्या नहीं होती, इसलिए अपने कोड के लिए नियम यह रखें: हमेशा df["col"] का उपयोग करें। टर्मिनल में तुरंत देखने के लिए डॉट ठीक है, उससे ज़्यादा कुछ नहीं।
लेबल से पंक्तियाँ: .loc
पंक्तियों को सादे ब्रैकेट्स से नहीं चुना जाता है। (नाम के साथ सादे ब्रैकेट्स का मतलब "कॉलम" होता है, और पांडास यह अंदाज़ा नहीं लगाएगा कि आपका क्या मतलब था।) पंक्तियों के लिए अपने दो टूल्स हैं, और पहला है .loc — label-based location (लेबल-आधारित स्थान)। आप इसे इंडेक्स से लेबल देते हैं:
print(orders.loc[2])order_id 1003
date 2024-03-02
branch north
product bag
category accessories
quantity 2
price 850.0
Name: 2, dtype: objectएक पंक्ति एक आड़ी Series के रूप में वापस आती है: कॉलम के नाम इसका इंडेक्स बन गए हैं, और इसका Name उस पंक्ति का लेबल, 2 है।
dtype: object को देखें। एक कॉलम का एक ही प्रकार होता है, लेकिन एक पंक्ति अलग-अलग कॉलमों के आर-पार चलती है — एक संख्या, कुछ टेक्स्ट, एक दशमलव मान — इसलिए एकमात्र प्रकार जो उन सभी को रख सकता है वह सामान्य object है। यही एक कारण है कि पांडास कॉलमों के रूप में सोचता है: एक पंक्ति प्रकारों को मिलाती है, एक कॉलम नहीं।
अब महत्वपूर्ण हिस्सा देखें। .loc से लेबलों की एक रेंज माँगें:
print(orders.loc[2:4])order_id date branch product category quantity price
2 1003 2024-03-02 north bag accessories 2 850.0
3 1004 2024-03-02 east bottle accessories 7 120.0
4 1005 2024-03-03 north eraser stationery 30 8.0तीन पंक्तियाँ: 2, 3 और 4। एक .loc स्लाइस अपने अंतिम मान को भी शामिल करता है। यह पायथन जानने वाले हर व्यक्ति को हैरान करता है, जहाँ range(2, 4) और list[2:4] 4 से पहले रुक जाते हैं। यह कोई असंगति नहीं है; इसका एक ठोस कारण है।
लेबल्स हमेशा संख्याएँ नहीं होते। यदि लेबल्स उत्पादों के नाम होते, तो आप loc["bag":"eraser"] जैसा कुछ लिखते। अंतिम मान को छोड़ने के लिए, आपको "eraser" के बाद वाले लेबल का नाम देना पड़ता — और नामों के साथ, बिना देखे यह जानना असंभव है कि "अगला नाम" कौन सा है। इसलिए लेबल्स के साथ, आप वह पहला नाम बताते हैं जो आपको चाहिए और वह आखिरी जो आपको चाहिए, और आपको दोनों मिलते हैं। पोज़ीशन अलग हैं: 4 के बाद अगली पोज़ीशन हमेशा 5 होती है, इसलिए वहाँ पायथन के "पहले रुकने" के नियम से कोई नुकसान नहीं होता।
पोज़ीशन से पंक्तियाँ: .iloc
दूसरा टूल है .iloc — integer location (पूर्णांक स्थान)। यह लेबल्स को पूरी तरह से अनदेखा करता है और पायथन लिस्ट की तरह ही 0 से स्थानों की गिनती करता है:
print(orders.iloc[2:4])order_id date branch product category quantity price
2 1003 2024-03-02 north bag accessories 2 850.0
3 1004 2024-03-02 east bottle accessories 7 120.0दो पंक्तियाँ, पोज़ीशन 2 और 3; पोज़ीशन 4 छूट गई है, जैसा कि पूरे पायथन में होता है। दोनों आउटपुट्स को अगल-बगल रखें: उसी टेबल पर, ब्रैकेट्स में उन्हीं संख्याओं के साथ, loc[2:4] ने तीन पंक्तियाँ दीं और iloc[2:4] ने दो।
चूँकि .iloc पोज़ीशनल है, इसलिए ऋणात्मक संख्याएँ अंत से गिनती करती हैं — जो सीधे आपके मैनेजर के सवाल का जवाब देती हैं:
print(orders.iloc[-3:])order_id date branch product category quantity price
5 1006 2024-03-03 south bag accessories 1 850.0
6 1007 2024-03-04 east pen stationery 20 15.0
7 1008 2024-03-04 north bottle accessories 4 120.0"आखिरी तीन" पोज़ीशन के बारे में एक सवाल है, इसलिए .iloc वह टूल है जो इससे मेल खाता है। .loc को बिल्कुल नहीं पता कि "आखिरी" का क्या मतलब है; वह केवल नाम जानता है।
लेबल और पोज़ीशन एक चीज़ नहीं हैं
अब तक, लेबल 2 और पोज़ीशन 2 एक ही पंक्ति थे, इसलिए आप उनके परिणामों से दोनों टूल्स में अंतर नहीं बता सकते थे। आखिरी तीन ऑर्डरों को उनकी अपनी टेबल के रूप में लें, और वे अलग हो जाते हैं:
last3 = orders.tail(3)
print(last3)order_id date branch product category quantity price
5 1006 2024-03-03 south bag accessories 1 850.0
6 1007 2024-03-04 east pen stationery 20 15.0
7 1008 2024-03-04 north bottle accessories 4 120.0पंक्तियों ने अपने लेबल बनाए रखे: 5, 6, 7। पांडास जानबूझकर उन्हें दोबारा नंबर नहीं देता — लेबल ही वह तरीका है जिससे टेबल को काटने के बाद भी कोई पंक्ति वही पंक्ति बनी रहती है। अब दोनों तरीकों से "पहली पंक्ति" माँगें:
print(last3.iloc[0])order_id 1006
date 2024-03-03
branch south
product bag
category accessories
quantity 1
price 850.0
Name: 5, dtype: objectlast3.loc[0]KeyError: 0.iloc[0] का मतलब है "पहले स्थान वाली पंक्ति", जो कि 5 लेबल वाला ऑर्डर है। .loc[0] का मतलब है "वह पंक्ति जिसका लेबल 0 है" — और इस टेबल में ऐसी कोई पंक्ति नहीं है, इसलिए पांडास KeyError देता है। यह वही ग़लती है जो कोर्स में आगे चलकर परेशान करती है: जब आप पंक्तियों को फ़िल्टर करते हैं या उन्हें सॉर्ट करते हैं — दोनों चीज़ें कोर्स में आगे आ रही हैं — पोज़ीशन बदल जाती हैं और लेबल नहीं बदलते। आगे के लिए याद रखने वाला नियम:
- जब सवाल पोज़ीशन या स्थान के बारे में हो — पहली, आखिरी, सॉर्ट करने के बाद शीर्ष तीन?
.ilocका उपयोग करें। - जब सवाल पहचान के बारे में हो — यह विशेष ऑर्डर, यह उत्पाद?
.locका उपयोग करें।
और सबसे बुरा मामला KeyError नहीं है। सबसे बुरा मामला तब होता है जब लेबल 0 टेबल में कहीं और मौजूद होता है: तब .loc[0] बिना किसी एरर के चुपचाप आपके मनचाहे रिकॉर्ड के बजाय कोई दूसरा रिकॉर्ड लौटा देता है।
.locएक नाम माँगता है,.ilocएक स्थान माँगता है। ताज़ा पढ़ी गई टेबल पर दोनों संयोग से सहमत होते हैं, इसलिए जो कोड उन्हें आपस में मिला देता है वह पहले दिन आपके हर चेक को पास कर जाता है — और जैसे ही टेबल काटी, फ़िल्टर या सॉर्ट की जाती है, वह बिना किसी एरर के गलत पंक्ति लौटाने लगता है।
पंक्तियों को सार्थक लेबल देना: set_index
अकाउंटेंट ने order 1006 के बारे में पूछा था। डिफ़ॉल्ट इंडेक्स के साथ आपको यह जानना पड़ता कि order 1006 लेबल 5 के तहत आता है — जो फ़ाइल के बारे में एक तथ्य है, ऑर्डर के बारे में नहीं। किसी पंक्ति का असली नाम उसका ऑर्डर नंबर होता है, इसलिए ऑर्डर नंबर को इंडेक्स बनाएँ:
by_id = orders.set_index("order_id")
print(by_id.head(3))
print(by_id.shape)date branch product category quantity price
order_id
1001 2024-03-01 north pen stationery 12 15.0
1002 2024-03-01 south notebook stationery 5 60.0
1003 2024-03-02 north bag accessories 2 850.0
(8, 6)तीन चीज़ें बदल गईं। ऑर्डर नंबर बाईं ओर इंडेक्स में चले गए। इंडेक्स का अब एक नाम है, order_id, जो उसके ऊपर अपनी पंक्ति में प्रिंट हुआ है। और आकार (8, 7) के बजाय (8, 6) हो गया है — order_id अब कॉलम नहीं रहा, यह इंडेक्स है। यह भी ध्यान दें कि set_index ने एक नई टेबल लौटाई, जिसे हमने by_id नाम दिया; orders स्वयं अछूती रही।
अब .loc सवाल की भाषा बोलता है:
print(by_id.loc[1006])date 2024-03-03
branch south
product bag
category accessories
quantity 1
price 850.0
Name: 1006, dtype: objectऔर एक लेबल स्लाइस अब ऑर्डर नंबरों की एक रेंज है, जिसमें दोनों छोर शामिल हैं:
print(by_id.loc[1003:1005, ["product", "quantity"]])product quantity
order_id
1003 bag 2
1004 bottle 7
1005 eraser 30.iloc में बिल्कुल कोई बदलाव नहीं हुआ है — पोज़ीशन पोज़ीशन ही रहती है, चाहे लेबल्स कुछ भी हों:
print(by_id.iloc[0:2])date branch product category quantity price
order_id
1001 2024-03-01 north pen stationery 12 15.0
1002 2024-03-01 south notebook stationery 5 60.0यहाँ दोनों टूल्स स्पष्ट रूप से अलग हो गए हैं: by_id.loc[0] अब एक KeyError होगा, क्योंकि 0 कोई ऑर्डर नंबर नहीं है, जबकि by_id.iloc[0] ऑर्डर 1001 है। यदि आपको कभी ऑर्डर नंबर को फिर से कॉलम के रूप में वापस चाहिए, तो by_id.reset_index() इसे वापस ले आता है।
ऐसा कॉलम चुनें जिसके मान अद्वितीय (unique) हों। इंडेक्स का उद्देश्य पंक्तियों को नाम देना है, और दो पंक्तियों द्वारा साझा किया गया नाम किसी एक की ओर इशारा नहीं कर सकता। देखें कि product के साथ क्या होता है, जो दोहराया गया है:
by_product = orders.set_index("product")
print(by_product.index.is_unique)
print(by_product.loc["bag"])False
order_id date branch category quantity price
product
bag 1003 2024-03-02 north accessories 2 850.0
bag 1006 2024-03-03 south accessories 1 850.0कोई एरर नहीं — लेकिन loc["bag"] ने Series के रूप में एक पंक्ति के बजाय दो पंक्तियों वाला DataFrame लौटा दिया। जिस कोड को एक पंक्ति की उम्मीद थी (जैसे, एक संख्या के रूप में उसकी price पढ़ना), उसे अब दो पंक्तियाँ मिलती हैं। यही कारण है कि जब भी आप पंक्तियों को खोजने के लिए कोई इंडेक्स सेट करते हैं, तो index.is_unique से एक पंक्ति की जाँच करना हमेशा उपयोगी होता है।
पंक्तियाँ और कॉलम एक साथ
.loc और .iloc दोनों कॉमा से अलग की गई दो चीज़ें लेते हैं: पहले पंक्तियाँ, बाद में कॉलम। प्रत्येक भाग एक एकल लेबल, एक लिस्ट, या एक स्लाइस हो सकता है:
print(orders.loc[2:4, ["product", "price"]])product price
2 bag 850.0
3 bottle 120.0
4 eraser 8.0print(orders.loc[[0, 3], ["branch", "product"]])branch product
0 north pen
3 east bottleस्लाइस कॉलमों के लिए भी काम करता है, .loc के समावेशी नियम के साथ — "branch से लेकर category तक का हर कॉलम"। केवल एक कोलन : का अर्थ है "सभी पंक्तियाँ":
print(orders.loc[:, "branch":"category"])branch product category
0 north pen stationery
1 south notebook stationery
2 north bag accessories
3 east bottle accessories
4 north eraser stationery
5 south bag accessories
6 east pen stationery
7 north bottle accessories.iloc पोज़ीशन के हिसाब से वही काम करता है। कॉलमों की गिनती भी 0 से की जाती है, इसलिए branch कॉलम 2 है और product कॉलम 3 है:
print(orders.iloc[[0, 3], [2, 3]])branch product
0 north pen
3 east bottleवही परिणाम जो दो ब्लॉक ऊपर .loc संस्करण का था — लेकिन ध्यान दें कि इसे पढ़ना कितना कठिन है। [2, 3] कुछ नहीं बताता; ["branch", "product"] सब कुछ साफ़ बताता है, और तब भी काम करता है यदि कोई फ़ाइल की शुरुआत में एक नया कॉलम जोड़ दे। जब आपको नाम पता हों तो नामों को प्राथमिकता दें।
कैसा आकार (shape) वापस मिलेगा?
आपको एक एकल मान, एक Series या एक DataFrame मिलता है, यह केवल इस बात पर निर्भर करता है कि आपने कॉमा के दोनों ओर क्या रखा है। एक एकल लेबल उस आयाम (dimension) को हटा देता है; एक लिस्ट या स्लाइस उसे बनाए रखता है:
print(type(by_id.loc[1006, "price"]).__name__)
print(type(by_id.loc[1006, ["product", "price"]]).__name__)
print(type(by_id.loc[[1003, 1006], "price"]).__name__)
print(type(by_id.loc[[1003, 1006], ["product", "price"]]).__name__)float64
Series
Series
DataFrame- एक लेबल, एक लेबल → एक एकल मान
- एक लेबल, एक लिस्ट या स्लाइस → एक
Series(एक पंक्ति) - एक लिस्ट या स्लाइस, एक लेबल → एक
Series(एक कॉलम) - एक लिस्ट या स्लाइस, एक लिस्ट या स्लाइस → एक
DataFrame
यह योजना बनाने का चरण 3 है — उत्तर का आकार तय करना — जो एक नियम में बदल गया है। यदि आप टेबल वापस चाहते हैं, भले ही वह एक पंक्ति की हो, तो दोनों तरफ लिस्ट दें: by_id.loc[[1006], ["price"]]।
एक एकल मान: .loc और .at
अकाउंटेंट का सवाल — order 1006 की कीमत क्या थी? — एक सेल है: एक पंक्ति का लेबल और एक कॉलम का नाम।
print(by_id.loc[1006, "price"])
print(by_id.at[1006, "price"])850.0
850.0दोनों एक ही संख्या देते हैं। .at केवल एक पंक्ति और एक कॉलम स्वीकार करता है, और कुछ नहीं, जो इसे थोड़ा तेज़ बनाता है और आपके इरादे को स्पष्ट करता है: यह एक सेल है। (पोज़ीशनल जुड़वां .iat है, जैसे by_id.iat[5, 5]।) जो पढ़ने में बेहतर लगे उसका उपयोग करें; .loc भी बढ़िया है।
एक एकल मान एक सामान्य संख्या होती है, इसलिए आप इसके साथ सीधे गणना कर सकते हैं। ऑर्डर 1004 का कुल मूल्य — मात्रा गुणा कीमत:
print(by_id.at[1004, "quantity"] * by_id.at[1004, "price"])840.0चयन (selection) अपने आप में एक अलग ऑब्जेक्ट है
वास्तविक प्रोग्रामों में सिलेक्शन का उपयोग करने से पहले एक और बात समझनी होगी: जब आप किसी सिलेक्शन को बदलते हैं तो क्या होता है।
import pandas as pd
orders = pd.read_csv("orders.csv")
prices = orders["price"]
prices[0] = 999.0
print(prices.head(2))
print(orders.loc[0, "price"])0 999.0
1 60.0
Name: price, dtype: float64
15.0prices बदल गया। orders नहीं बदला। पांडास 3 में, प्रत्येक सिलेक्शन एक अलग कॉपी (प्रतिलिपि) के रूप में व्यवहार करता है: आप इसे स्वतंत्र रूप से बदल सकते हैं और मूल टेबल कभी नहीं बदलती। (आंतरिक रूप से पांडास वास्तव में डेटा की प्रतिलिपि तब तक नहीं बनाता जब तक आप उसमें कुछ लिखते नहीं हैं — इस तंत्र का नाम कॉपी-ऑन-राइट (Copy-on-Write) है — लेकिन आपको जिस नियम की आवश्यकता है वह इसका व्यवहार है, आंतरिक तंत्र नहीं।)
यही बात कई कॉलमों के चयन पर भी लागू होती है:
stock = orders[["product", "price"]]
stock["price"] = 0
print(orders["price"].head(2))0 15.0
1 60.0
Name: price, dtype: float64यह सुरक्षित व्यवहार है: एक फ़ंक्शन जो कोई सिलेक्शन लेता है और उसे संपादित करता है, वह आपकी मुख्य टेबल को आपके पीछे नुकसान नहीं पहुँचा सकता। लेकिन इसका एक परिणाम है जिसे आपको जानना आवश्यक है। यदि आपका इरादा मूल टेबल को बदलने का है, तो आपको इसे मूल टेबल पर ही, एक ही चरण में, .loc के साथ करना होगा:
orders.loc[0, "price"] = 16.0
print(orders.loc[0, "price"])16.0दो चरणों वाला लुभावना तरीका — पहले एक कॉलम चुनना, फिर उसमें एक सेल सेट करना — काम नहीं करता, और पांडास 3 आपको यह साफ़ बताता है:
orders["price"][0] = 1.0ChainedAssignmentError: A value is being set on a copy of a DataFrame or Series through chained assignment.
Such chained assignment never works to update the original DataFrame or Series, because the intermediate object on which we are setting values always behaves as a copy (due to Copy-on-Write).
Try using '.loc[row_indexer, col_indexer] = value' instead, to perform the assignment in a single step.
See the documentation for a more detailed explanation: https://pandas.pydata.org/pandas-docs/stable/user_guide/copy_on_write.html#chained-assignmentprint(orders.loc[0, "price"])16.0अभी भी 16.0 — असाइनमेंट एक अस्थायी कॉपी में चला गया और उसे छोड़ दिया गया। orders["price"] ने एक सिलेक्शन बनाया, और [0] = 1.0 ने उसे बदला, orders को नहीं। इसे चेन्ड असाइनमेंट (chained assignment) कहते हैं: = के बाईं ओर लगातार दो ब्रैकेट्स। इसका समाधान हमेशा वही होता है जो चेतावनी में बताया गया है: पंक्ति और कॉलम दोनों के साथ एक ही .loc, जैसे orders.loc[0, "price"] = 1.0।
यदि आप पुराने ट्यूटोरियल पढ़ते हैं, तो आप इस विषय को SettingWithCopyWarning और इस सलाह के साथ वर्णित देखेंगे कि कभी मूल टेबल बदलती थी और कभी नहीं। वह पांडास 1 और 2 था। पांडास 3 में नियम सरल और हमेशा एक जैसा है: एक सिलेक्शन कभी भी मूल को नहीं बदलता; मूल पर .loc बदलता है।
एक संपूर्ण उदाहरण
अध्याय की शुरुआत के तीनों अनुरोधों का उत्तर एक ही प्रोग्राम में दिया गया है। select_orders.py:
import pandas as pd
orders = pd.read_csv("orders.csv")
# 1. Check what arrived before pointing into it
print("Shape :", orders.shape)
print("Columns:", list(orders.columns))
# 2. Name the rows by what they are
by_id = orders.set_index("order_id")
print("Order ids unique:", by_id.index.is_unique)
print()
# Stock team: two columns, every row
stock = orders[["product", "quantity"]]
print("Stock view:", stock.shape)
print(stock.head(3))
print()
# Accountant: one order by its number, then one cell
print(by_id.loc[1006, ["product", "quantity", "price"]])
print("Order 1006 total:", by_id.at[1006, "quantity"] * by_id.at[1006, "price"])
print()
# Manager: the last three orders, a question about position
print(by_id.iloc[-3:, [1, 2, 4]])Shape : (8, 7)
Columns: ['order_id', 'date', 'branch', 'product', 'category', 'quantity', 'price']
Order ids unique: True
Stock view: (8, 2)
product quantity
0 pen 12
1 notebook 5
2 bag 2
product bag
quantity 1
price 850.0
Name: 1006, dtype: object
Order 1006 total: 850.0
branch product quantity
order_id
1006 south bag 1
1007 east pen 20
1008 north bottle 4इसे इस तरह क्यों लिखा गया है:
- यह इशारा करने से पहले देखता है।
shapeऔरlist(columns)पहले प्रिंट किए जाते हैं, ताकि किसी भी सिलेक्शन के विफल होने से पहले ग़लत वर्तनी या स्पेस वाला कॉलम नाम दिखाई दे जाए। - यह जाँचता है कि इंडेक्स अद्वितीय (unique) है ऑर्डर खोजने के लिए इसका उपयोग करने से पहले, ताकि
by_id.loc[1006]गारंटी के साथ एक पंक्ति हो औरby_id.at[...]एक संख्या। - प्रत्येक अनुरोध उस टूल का उपयोग करता है जो उसके सवाल से मेल खाता है। नाम से कॉलम के लिए ब्रैकेट्स; ऑर्डर की पहचान से खोजने के लिए
.locऔर.at; और पोज़ीशन से "आखिरी तीन" के लिए.iloc। - यह स्टॉक व्यू का आकार प्रिंट करता है —
(8, 2)बिल्कुल वही स्केच है: हर ऑर्डर, दो कॉलम। - अंतिम सिलेक्शन सुधारने योग्य है।
by_idमें[1, 2, 4]का अर्थbranch,product,quantityहै — ध्यान दें कि पोज़ीशन एक स्थान खिसक गई क्योंकिorder_idइंडेक्स बन गया। पोज़ीशन नाज़ुक होती हैं। आपके अपने कोड में,by_id.iloc[-3:][["branch", "product", "quantity"]]याby_id.loc[by_id.index[-3:], ["branch", "product", "quantity"]]नामों के साथ वही बात अधिक स्पष्टता से कहेगा।
जब यह काम न करे
KeyError: 'Price' बिल्कुल उस नाम का कोई कॉलम नहीं है। कॉलम के नाम केस-सेंसिटिव होते हैं: price और Price अलग-अलग नाम हैं। list(df.columns) प्रिंट करें और वहाँ से नाम कॉपी करें। नामों की लिस्ट के साथ, orders[["product", "Price"]], संदेश KeyError: "['Price'] not in index" बन जाता है और ठीक बताता है कि कौन सा गायब है; डॉट के साथ, orders.Price, यह AttributeError: 'DataFrame' object has no attribute 'Price' होता है। एक ही कारण, एक ही समाधान।
KeyError: 'price' — हालाँकि फ़ाइल में price साफ़ दिख रहा है हेडर में संभवतः कॉमा के बाद स्पेस हैं, जैसे order_id, product, price, और वे स्पेस नामों का हिस्सा बन गए:
from io import StringIO
import pandas as pd
raw = "order_id, product, price\n1001, pen, 15.0\n"
padded = pd.read_csv(StringIO(raw))
print(list(padded.columns))
padded["price"]['order_id', ' product', ' price']
KeyError: 'price'लिस्ट ' price' में शुरुआती स्पेस दिखाती है, यही वजह है कि अध्याय तीन में आपको कॉलमों को लिस्ट के रूप में प्रिंट करने के लिए कहा गया था। फ़ाइल पढ़ते समय इसे pd.read_csv("file.csv", skipinitialspace=True) से ठीक करें, या बाद में df.columns = df.columns.str.strip() से।
KeyError: ('product', 'price') आपने orders["product", "price"] लिखा — ब्रैकेट्स की एक ही जोड़ी। अंदरूनी लिस्ट के बिना, पायथन दोनों नामों को एक टपल के रूप में पास करता है, और पांडास ('product', 'price') नाम का एक ही कॉलम ढूँढता है। orders[["product", "price"]] लिखें।
.loc से KeyError: 0 आपने .loc के साथ पोज़ीशन का उपयोग किया। या तो टेबल काटी गई थी (tail, फ़िल्टर, सॉर्ट) जिससे लेबल 0 चला गया, या आपने इंडेक्स सेट किया और लेबल्स अब ऑर्डर नंबर बन गए हैं। यदि आपका मतलब "पहली पंक्ति" है, तो .iloc[0] लिखें। जिस टेबल का इंडेक्स टेक्स्ट है, उस पर स्लाइस के साथ की गई यही ग़लती — orders.set_index("product").loc[0:2] — इसके बजाय TypeError: cannot do slice indexing on Index with these indexers [0] of type int देती है; समाधान वही है, .iloc[0:2]।
IndexError: single positional indexer is out-of-bounds .iloc को ऐसी पोज़ीशन दी गई थी जो मौजूद नहीं है — आठ पंक्तियों वाली टेबल पर orders.iloc[8], जिसकी पोज़ीशन 0 से 7 तक होती हैं। df.shape जाँचें; आखिरी पंक्ति हमेशा df.iloc[-1] होती है। कॉलम की पोज़ीशन बहुत बड़ी होने पर भी यही संदेश आता है, जैसे orders.iloc[:, 7]।
ValueError: Location based indexing can only have [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] types आपने .iloc को कॉलम का नाम दे दिया: orders.iloc[0, "branch"]। .iloc केवल पोज़ीशन लेता है। लेबल के साथ .loc का उपयोग करें — orders.loc[0, "branch"] — या, यदि आपको वास्तव में पोज़ीशन की आवश्यकता है, तो उसे खोजें: orders.columns.get_loc("branch") से 2 मिलता है।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
वही टेबल, ब्रैकेट्स में वही संख्याएँ। क्या प्रिंट होगा?
from io import StringIO
import pandas as pd
# Stands in for orders.csv, so this snippet runs on its own.
RAW = """order_id,date,branch,product,category,quantity,price
1001,2024-03-01,north,pen,stationery,12,15.0
1002,2024-03-01,south,notebook,stationery,5,60.0
1003,2024-03-02,north,bag,accessories,2,850.0
1004,2024-03-02,east,bottle,accessories,7,120.0
1005,2024-03-03,north,eraser,stationery,30,8.0
1006,2024-03-03,south,bag,accessories,1,850.0
1007,2024-03-04,east,pen,stationery,20,15.0
1008,2024-03-04,north,bottle,accessories,4,120.0
"""
orders = pd.read_csv(StringIO(RAW))
print(len(orders.loc[2:5]), len(orders.iloc[2:5]))- A4 4
- B3 3
- C4 3
- D3 4
इसका उद्देश्य पिछले तीन ऑर्डरों में से पहले ऑर्डर का प्रोडक्ट प्रिंट करना है। वास्तव में क्या होता है, और क्यों?
from io import StringIO
import pandas as pd
# Stands in for orders.csv, so this snippet runs on its own.
RAW = """order_id,date,branch,product,category,quantity,price
1001,2024-03-01,north,pen,stationery,12,15.0
1002,2024-03-01,south,notebook,stationery,5,60.0
1003,2024-03-02,north,bag,accessories,2,850.0
1004,2024-03-02,east,bottle,accessories,7,120.0
1005,2024-03-03,north,eraser,stationery,30,8.0
1006,2024-03-03,south,bag,accessories,1,850.0
1007,2024-03-04,east,pen,stationery,20,15.0
1008,2024-03-04,north,bottle,accessories,4,120.0
"""
orders = pd.read_csv(StringIO(RAW))
last3 = orders.tail(3)
# Wanted: the product of the first of these three orders
print(last3.loc[0, "product"])- Aयह `pen` प्रिंट करता है, जो मूल टेबल की पहली पंक्ति का प्रोडक्ट है
- Bयह `bag` प्रिंट करता है, जो इन तीन पंक्तियों में से पहली पंक्ति का प्रोडक्ट है
- C`KeyError: 0` — `tail(3)` ने लेबल्स 5, 6 और 7 को बनाए रखा, और `.loc` लेबल 0 की तलाश करता है
- D`IndexError` — टेबल में केवल तीन पंक्तियाँ हैं
आपको केवल price कॉलम वाला एक DataFrame चाहिए — Series नहीं। कौन सी लाइन आपको यह देती है?
- Aorders["price"]
- Borders.price
- Corders.loc[:, "price"]
- Dorders[["price"]]
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
उसी orders.csv का उपयोग करके select.py लिखें। किसी भी कोड से पहले, एक कमेंट में लिखें कि प्रत्येक सिलेक्शन को क्या वापस देना चाहिए — एक मान, एक Series या एक DataFrame — और कितनी पंक्तियाँ। प्रोग्राम को चार शर्तों को पूरा करना होगा:
- कॉलम हमेशा नाम से चुने जाते हैं: एक साथ
date,branchऔरquantityकाshapeप्रिंट करें। - यह जाँचने के बाद कि इंडेक्स अद्वितीय है,
order_idद्वारा इंडेक्स की गई टेबल पर पहचान से ऑर्डर खोजे जाते हैं: ऑर्डर 1007 के लिए पूरी पंक्ति प्रिंट करें, फिर ऑर्डर 1002 से 1005 के लिएproductऔरbranchप्रिंट करें — ये चारों। - "पहले" और "आखिरी" का उत्तर पोज़ीशन से दिया जाता है: पहले दो और आखिरी दो ऑर्डरों के लिए
productऔरpriceप्रिंट करें; फिर,.atके साथ, ऑर्डर 1005 की क्वांटिटी और ऑर्डर 1003 का कुल मूल्य (quantity × price)। - इंडेक्स की गई टेबल में एक ही
.locके साथ ऑर्डर 1001 की कीमत बदलकर16.0करें, और यह साबित करने के लिए इसे प्रिंट करें कि बदलाव हुआ है।
आपका आउटपुट बिल्कुल ऐसा होना चाहिए:
(8, 3)
unique: True
date 2024-03-04
branch east
product pen
category stationery
quantity 20
price 15.0
Name: 1007, dtype: object
product branch
order_id
1002 notebook south
1003 bag north
1004 bottle east
1005 eraser north
product price
order_id
1001 pen 15.0
1002 notebook 60.0
product price
order_id
1007 pen 15.0
1008 bottle 120.0
qty of 1005: 30
total of 1003: 1700.0
price of 1001: 16.0फिर अनुमान लगाएं, अपना अनुमान लिख लें, और उसके बाद ही इन तीन पंक्तियों में से प्रत्येक को चलाएँ:
by_id.loc[0]orders.iloc[8]by_id["price"][1001] = 99.0— और बाद में, ऑर्डर 1001 की कीमत फिर से प्रिंट करें
समाधान
पहले योजना बनाएं। कमेंट ब्लॉक "कोड लिखने से पहले" के चरण 3 का स्केच है — कि प्रत्येक सिलेक्शन को क्या लौटाना चाहिए:
- तीन कॉलम →
orders[[...]]→(8, 3)आकार का एकDataFrame - एक ऑर्डर, पहचान से →
by_id.loc[1007]→ एकSeries(एक पंक्ति) - पहचान से चार ऑर्डर, दो कॉलम →
by_id.loc[1002:1005, [...]]→ एक 4 × 2DataFrame, क्योंकि.locमें 1005 शामिल है - पोज़ीशन से पहले दो और आखिरी दो →
.iloc[:2]और.iloc[-2:]→ दो 2 × 2DataFrame - एकल सेल →
.at→ सामान्य संख्याएँ - मूल टेबल को बदलना →
by_idपर एक.loc→ टेबल खुद बदल जाती है
select.py:
import pandas as pd
orders = pd.read_csv("orders.csv")
# Columns by name -> a DataFrame of 8 rows, 3 columns
print(orders[["date", "branch", "quantity"]].shape)
# Rows named by their order number; check the names are unique first
by_id = orders.set_index("order_id")
print("unique:", by_id.index.is_unique)
# One order by identity -> a Series; four orders -> 4 x 2 (loc includes 1005)
print(by_id.loc[1007])
print(by_id.loc[1002:1005, ["product", "branch"]])
# First two and last two by place -> .iloc for rows, names for columns
print(by_id.iloc[:2][["product", "price"]])
print(by_id.iloc[-2:][["product", "price"]])
# Single cells -> plain numbers
print("qty of 1005:", by_id.at[1005, "quantity"])
print("total of 1003:", by_id.at[1003, "quantity"] * by_id.at[1003, "price"])
# Change the original, in one step
by_id.loc[1001, "price"] = 16.0
print("price of 1001:", by_id.at[1001, "price"])(8, 3)
unique: True
date 2024-03-04
branch east
product pen
category stationery
quantity 20
price 15.0
Name: 1007, dtype: object
product branch
order_id
1002 notebook south
1003 bag north
1004 bottle east
1005 eraser north
product price
order_id
1001 pen 15.0
1002 notebook 60.0
product price
order_id
1007 pen 15.0
1008 bottle 120.0
qty of 1005: 30
total of 1003: 1700.0
price of 1001: 16.0प्रत्येक परिणाम योजना से मेल खाता है: तीन कॉलमों के लिए (8, 3), 1002:1005 के लिए चार ऑर्डर क्योंकि .loc अपने अंतिम छोर को शामिल करता है, और पोज़ीशनल सिलेक्शन के लिए दो-दो पंक्तियाँ। शर्त 3 में पंक्तियाँ पोज़ीशन से और कॉलम नाम से आते हैं — पंक्तियों के लिए .iloc, फिर नामों की एक लिस्ट — ताकि कोड अपने इरादे को स्पष्ट रखे।
अब तीनों भविष्यवाणियाँ:
by_id.loc[0]KeyError: 0लेबल्स अब ऑर्डर नंबर हैं; कोई ऑर्डर 0 नहीं है। पोज़ीशन से पहली पंक्ति by_id.iloc[0] होगी।
orders.iloc[8]IndexError: single positional indexer is out-of-boundsआठ पंक्तियों का अर्थ है पोज़ीशन 0 से 7। अंतिम पंक्ति orders.iloc[7] है, या बेहतर कहें तो orders.iloc[-1]।
by_id["price"][1001] = 99.0ChainedAssignmentError: A value is being set on a copy of a DataFrame or Series through chained assignment.
Such chained assignment never works to update the original DataFrame or Series, because the intermediate object on which we are setting values always behaves as a copy (due to Copy-on-Write).
Try using '.loc[row_indexer, col_indexer] = value' instead, to perform the assignment in a single step.
See the documentation for a more detailed explanation: https://pandas.pydata.org/pandas-docs/stable/user_guide/copy_on_write.html#chained-assignmentprint(by_id.at[1001, "price"])16.0अभी भी 16.0: by_id["price"] ने एक अलग सिलेक्शन बनाया और 99.0 उसमें चला गया, by_id में नहीं। शर्त 4 ने काम किया और इसने नहीं किया, और अंतर केवल एक .loc बनाम एक पंक्ति में लगातार दो ब्रैकेट्स का है।
Step 6 of 6
चुनौती — the chapter quiz
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
Sign in to take the quiz