Series और DataFrame — पांडास की दो मुख्य चीज़ें
कॉलम क्या है, टेबल क्या है, और क्यों एक कॉलम की सभी वैल्यूज़ का एक ही टाइप होना अनिवार्य है। df["col"] और df[["col"]] के अंतर के साथ।
- 1समस्या
- 2समझें
- 3उदाहरण
- 4अनुमान
- 5स्वयं करें
- 6चुनौती
वह समस्या जिसे हम हल कर रहे हैं
पिछले अध्याय में एक लाइन लिखी गई थी, और उसने काम किया:
print(sales["quantity"].sum())19यह लाइन पढ़ने में आसान है, लेकिन इसके अंदर एक सवाल छिपा हुआ है। sales["quantity"] ने असल में क्या लौटाया? एक लिस्ट? लेकिन पायथन लिस्ट्स में .sum() नाम का कोई मेथड नहीं होता — पायथन में [12, 5, 2].sum() लिखने पर एरर आ जाता है।
यह उत्तर जानना बहुत ज़रूरी है, क्योंकि पांडास में आप हमेशा दो में से किसी एक चीज़ को थामे रहते हैं, और लगभग हर भ्रम इसी एक सवाल से शुरू होता है: इस समय मेरे हाथ में क्या है? केवल एक कॉलम, या फिर पूरी की पूरी टेबल?
यह अध्याय उन्हीं दो चीज़ों के बारे में है: उनके नाम, उनके आकार, और जो चीज़ उन्हें एक-दूसरे से अलग करती है।
इस अध्याय के अंत में आप कर पाएंगे
- एक वाक्य में यह बताना कि
SeriesऔरDataFrameके बीच क्या अंतर है - एक
Seriesबनाना और उसके इंडेक्स, वैल्यूज़ और टाइप का अलग-अलग निरीक्षण करना - यह समझाना कि एक कॉलम की सभी वैल्यूज़ का एक ही प्रकार (type) होना क्यों ज़रूरी है
df["col"]औरdf[["col"]]का उपयोग करते समय यह स्पष्ट जानना कि कौन क्या हैKeyErrorपढ़ना और कॉलम नाम में हुई सटीक गड़बड़ी को पहचानना
ज़रूरी शर्तें: पांडास इंस्टॉल करना और आपकी पहली टेबल।
Series — एक अकेला कॉलम
छोटी इकाई से शुरुआत करते हैं। एक Series वैल्यूज़ का एक क्रम है, जहाँ प्रत्येक वैल्यू एक नाम के साथ जुड़ी होती है:
import pandas as pd
quantity = pd.Series([12, 5, 2])
print(quantity)0 12
1 5
2 2
dtype: int64तीन वैल्यूज़ अंदर गईं, और तीन जोड़े बाहर आए। बाईं ओर दिखने वाले 0, 1, 2 इंडेक्स (index) हैं — प्रत्येक वैल्यू के लिए एक नाम। आपने उन्हें नहीं दिया था; पांडास ने खुद शून्य से गिनती शुरू की।
और नीचे की तरफ़, dtype: int64 — पूरी सीरीज़ का डेटा टाइप। एक ही टाइप, प्रत्येक वैल्यू के लिए अलग नहीं। यही चीज़ पांडास को तेज़ बनाती है, और यही इसका मुख्य नियम भी है।
इन तीनों भागों को अलग-अलग देखा जा सकता है:
import pandas as pd
quantity = pd.Series([12, 5, 2])
print(quantity.index)
print(quantity.values)
print(quantity.dtype)RangeIndex(start=0, stop=3, step=1)
[12 5 2]
int64RangeIndex का मतलब है कि इंडेक्स सिर्फ़ एक गिनती है — शून्य से शुरू होकर एक-एक आगे बढ़ती हुई। values बिना नामों के वास्तविक वैल्यूज़ हैं। और dtype पूरे कॉलम का डेटा टाइप है।
इंडेक्स का केवल संख्या होना ज़रूरी नहीं है:
import pandas as pd
quantity = pd.Series([12, 5, 2], index=["pen", "notebook", "bag"])
print(quantity)
print(quantity["notebook"])pen 12
notebook 5
bag 2
dtype: int64
5अब पंक्तियों के नाम उत्पादों के नाम पर हैं, और उस नाम से वैल्यू प्राप्त की जा सकती है। यह पायथन डिक्शनरी जैसा लगता है, और समानता वास्तविक भी है — लेकिन एक बड़े अंतर के साथ:
import pandas as pd
quantity = pd.Series([12, 5, 2], index=["pen", "notebook", "bag"])
print(quantity * 2)pen 24
notebook 10
bag 4
dtype: int64पूरे कॉलम को बिना किसी लूप के एक साथ दो से गुणा कर दिया गया। किसी डिक्शनरी के साथ ऐसा करने का मतलब है कि हर वैल्यू पर खुद लूप चलाना। किसी Series पर कोई ऑपरेशन चलाएँ और पांडास उसे हर वैल्यू पर लागू कर देता है — और आगे का हर अध्याय इसी व्यवहार पर टिका है।
DataFrame — कई कॉलम्स, एक साझा इंडेक्स
एक DataFrame कई Series का एक समूह है जो कंधे से कंधा मिलाकर चलते हैं और एक ही इंडेक्स साझा करते हैं।
import pandas as pd
sales = pd.DataFrame({
"product": ["pen", "notebook", "bag"],
"quantity": [12, 5, 2],
"price": [15.0, 60.0, 850.0],
})
print(sales)
print(sales.shape)
print(sales.columns)product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0
(3, 3)
Index(['product', 'quantity', 'price'], dtype='object')वह वाक्यांश "एक ही इंडेक्स साझा करते हैं" ही इसका मुख्य सार है। इंडेक्स 0 पर मौजूद product, quantity और price सब एक ही चीज़ की बात कर रहे हैं — एक पेन। इंडेक्स ही वह धागा है जो तीन अलग-अलग कॉलम्स को पंक्तियों (rows) में पिरोता है।
एक टेबल, कई प्रकार — लेकिन एक कॉलम, एक प्रकार
import pandas as pd
sales = pd.DataFrame({
"product": ["pen", "notebook", "bag"],
"quantity": [12, 5, 2],
"price": [15.0, 60.0, 850.0],
})
print(sales.dtypes)product object
quantity int64
price float64
dtype: objectतीन कॉलम, तीन प्रकार। int64 पूर्ण संख्याएँ हैं, float64 दशमलव संख्याएँ, और object — जिसका आमतौर पर मतलब टेक्स्ट होता है।
ध्यान दें कि यहाँ कोई str नहीं है। पांडास के डेटा टाइप्स NumPy से आते हैं, जहाँ प्रत्येक वैल्यू समान मात्रा में मेमोरी लेती है — जो संख्याओं के लिए संभव है, लेकिन अलग-अलग लंबाई के टेक्स्ट के लिए नहीं। इसलिए टेक्स्ट को संभालने के लिए पांडास पायथन ऑब्जेक्ट्स के पॉइंटर्स रखता है, और इसी व्यवस्था को object कहा जाता है।
अब सबसे महत्वपूर्ण नियम: एक कॉलम में प्रत्येक वैल्यू एक ही प्रकार साझा करती है। तो क्या होता है जब संख्याओं और टेक्स्ट को एक साथ मिला दिया जाए?
import pandas as pd
mixed = pd.Series([1, "two", 3.0])
print(mixed)
print(mixed.dtype)0 1
1 two
2 3.0
dtype: objectपांडास कोई एरर नहीं देता — यह पूरे कॉलम को उपलब्ध सबसे लचीले प्रकार object में बदल देता है। इसका परिणाम तुरंत कोई तमाशा खड़ा नहीं करता, बल्कि यह चुपचाप होता है: कॉलम अब संख्यात्मक नहीं रहा, इसलिए इस पर .mean() काम नहीं करेगा और .sum() टेक्स्ट को आपस में जोड़ना शुरू कर देगा। किसी CSV की एक पंक्ति में एक भटकी हुई N/A वैल्यू ठीक यही करती है, और यही छठे अध्याय का मुख्य विषय है।
मेरे हाथ में क्या है — Series या DataFrame?
import pandas as pd
sales = pd.DataFrame({
"product": ["pen", "notebook", "bag"],
"quantity": [12, 5, 2],
"price": [15.0, 60.0, 850.0],
})
column = sales["quantity"]
print(type(column))
print(type(sales))
print(column.mean())<class 'pandas.core.series.Series'>
<class 'pandas.core.frame.DataFrame'>
6.333333333333333और यह उस सवाल का जवाब है जिससे यह अध्याय शुरू हुआ था। sales["quantity"] कोई लिस्ट नहीं है, यह एक Series है — और एक Series में .sum(), .mean(), .max() और बाकी सभी मेथड्स होते हैं।
यहाँ एक ऐसा जोड़ा भी है जो पहली बार में हर किसी को हैरान करता है:
import pandas as pd
sales = pd.DataFrame({
"product": ["pen", "notebook", "bag"],
"quantity": [12, 5, 2],
"price": [15.0, 60.0, 850.0],
})
print(sales["quantity"])
print("---")
print(sales[["quantity"]])0 12
1 5
2 2
Name: quantity, dtype: int64
---
quantity
0 12
1 5
2 2केवल एक अतिरिक्त ब्रैकेट, और परिणाम बिल्कुल अलग तरह की चीज़ बन जाता है। पहला एक Series है — एक अकेला कॉलम, जिसका नाम और प्रकार नीचे प्रिंट होता है। दूसरा एक DataFrame है — एक टेबल जिसमें संयोगवश केवल एक कॉलम है, इसलिए कॉलम हेडिंग ऊपर बैठती है।
नियम यह है कि आंतरिक चौकोर ब्रैकेट (square brackets) का अर्थ है कॉलम्स की एक लिस्ट, और लिस्ट मांगने पर आपको एक टेबल मिलती है। इसलिए sales[["product", "price"]] दो कॉलम वाली टेबल देता है।
इस अंतर को याद रखना क्यों ज़रूरी है? क्योंकि यहीं से एरर मैसेजेस अलग रास्ते पकड़ते हैं। एकSeriesमें.mean()होता है लेकिन कॉलम नाम नहीं होते; एकDataFrameकॉलम्स चुनता है लेकिन कोई एक संख्या नहीं लौटाता। जब कोई मैसेज कहे कि ऑब्जेक्ट में ऐसा कोई एट्रिब्यूट नहीं है, तो पहला सवाल यही होना चाहिए: वास्तव में मेरे हाथ में दोनों में से कौन सी चीज़ है?
पूर्ण उदाहरण
inventory.py:
import pandas as pd
# उत्पादों के नाम इंडेक्स बन जाते हैं, ताकि किसी पंक्ति तक नाम से पहुँचा जा सके।
stock = pd.DataFrame(
{
"quantity": [12, 5, 2, 30],
"price": [15.0, 60.0, 850.0, 8.0],
},
index=["pen", "notebook", "bag", "eraser"],
)
print(stock)
print()
print("Shape :", stock.shape)
print("Columns :", list(stock.columns))
print("Index :", list(stock.index))
print()
# एक कॉलम एक Series है, इसलिए कोई भी ऑपरेशन एक साथ हर वैल्यू पर लागू होता है।
value = stock["quantity"] * stock["price"]
print("Value per product:")
print(value)
print()
print("Total value:", value.sum())quantity price
pen 12 15.0
notebook 5 60.0
bag 2 850.0
eraser 30 8.0
Shape : (4, 2)
Columns : ['quantity', 'price']
Index : ['pen', 'notebook', 'bag', 'eraser']
Value per product:
pen 180.0
notebook 300.0
bag 1700.0
eraser 240.0
dtype: float64
Total value: 2420.0यहाँ दो बातें ध्यान देने योग्य हैं।
पहला, stock["quantity"] * stock["price"] ने दो Series को गुणा किया और एक अन्य Series तैयार की। पांडास ने उन्हें इंडेक्स के आधार पर मिलाया — पेन की मात्रा पेन की कीमत के साथ, बैग की मात्रा बैग की कीमत के साथ। नाम से, पंक्ति के क्रम से नहीं। यह व्यवहार बाद में दो टेबलों को आपस में जोड़ने (join करने) की नींव है।
दूसरा, परिणामी कॉलम का डेटा प्रकार float64 है, हालाँकि quantity int64 थी। किसी पूर्ण संख्या को दशमलव से गुणा करने पर दशमलव मिलता है — सामान्य पायथन जैसा ही नियम; पांडास यहाँ अपनी तरफ़ से कुछ नया नहीं कर रहा है।
जब यह काम न करे
KeyError: 'Quantity' ऐसा कोई कॉलम मौजूद नहीं है। कॉलम के नाम केस-सेंसिटिव (case-sensitive) होते हैं, और CSV फ़ाइल से आने वाले नामों में अक्सर आगे या पीछे कोई स्पेस छूटा होता है। यह ठीक-ठीक देखने के लिए कि वहाँ क्या है, print(list(df.columns)) चलाएँ — उन्हें लिस्ट के रूप में प्रिंट करने से हर एक के दोनों ओर कोट्स लग जाते हैं, जिससे कोई भी स्पेस साफ़ दिख जाता है।
संख्यात्मक कॉलम पर गणना करते समय AttributeError: 'DataFrame' object has no attribute 'mean_price' df.column_name भी कॉलम लाता है, लेकिन केवल सरल नामों के लिए — तब नहीं जब नाम में स्पेस हो, संख्या से शुरू होता हो, या count जैसे किसी पांडास मेथड से टकराता हो। df["column_name"] हमेशा काम करता है, इसलिए हमेशा इसी को लिखने की आदत बनाएँ।
TypeError: unsupported operand type(s) कॉलम संभवतः संख्यात्मक नहीं है। df.dtypes की जाँच करें; वहाँ object होने का मतलब है कि कहीं न कहीं टेक्स्ट मिला हुआ है।
.sum() संख्याओं को जोड़ने के बजाय टेक्स्ट को जोड़ रहा है वही कारण — कॉलम का प्रकार object है। एक ही पंक्ति में एक N/A या एक खाली सेल पूरे कॉलम के प्रकार को बदलने के लिए काफ़ी है।
ValueError: All arrays must be of the same length pd.DataFrame({...}) को दी गई लिस्ट्स की लंबाई समान नहीं है। प्रत्येक कॉलम को समान संख्या में वैल्यूज़ की आवश्यकता होती है, क्योंकि पंक्तियों को एक साझा इंडेक्स पर संरेखित होना पड़ता है।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
तीन मान दिए गए थे। प्रिंट होने पर वास्तव में क्या दिखाई देता है?
import pandas as pd
quantity = pd.Series([12, 5, 2])
print(quantity)- A0 12 1 5 2 2 dtype: int64
- B12 5 2
- C[12, 5, 2]
- D12 5 2 dtype: int64
दोनों लाइनों में केवल एक अतिरिक्त ब्रैकेट का अंतर है। type() क्या रिपोर्ट करता है?
import pandas as pd
sales = pd.DataFrame({
"product": ["pen", "notebook", "bag"],
"quantity": [12, 5, 2],
"price": [15.0, 60.0, 850.0],
})
print(type(sales["quantity"]))
print(type(sales[["quantity"]]))- Aपहला एक Series, दूसरा एक DataFrame
- Bदोनों Series
- Cदोनों DataFrame
- Dपहला एक DataFrame, दूसरा एक Series
संख्याओं और टेक्स्ट को एक ही कॉलम में मिला दिया गया है। पांडास क्या करता है?
import pandas as pd
mixed = pd.Series([1, "two", 3.0])
print(mixed.dtype)- Aयह कोई एरर नहीं देता — यह पूरे कॉलम का प्रकार `object` बना देता है
- Bएक `TypeError` — दो प्रकार एक ही कॉलम में नहीं रह सकते
- Cयह टेक्स्ट को हटा देता है और कॉलम को `float64` रखता है
- Dयह प्रत्येक मान के लिए एक अलग प्रकार रखता है
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
कम से कम पाँच किताबों का एक DataFrame रखने वाली library.py नामक फ़ाइल लिखें — शीर्षकों को इंडेक्स के रूप में रखें, और प्रतियों की संख्या (पूर्ण संख्याएँ), क़ीमत (दशमलव) और लेखक का नाम (टेक्स्ट) के लिए कॉलम्स बनाएँ।
फिर प्रिंट करें:
- पूरी टेबल, इसका
shape, और इसकेdtypes - केवल क़ीमत वाला कॉलम — और
type()से दिखाएँ कि यह एकSeriesहै - दोहरे ब्रैकेट्स के साथ क़ीमत वाला कॉलम — और दिखाएँ कि यह एक
DataFrameहै - प्रत्येक किताब का कुल मूल्य (प्रतियाँ × क़ीमत), और उन सभी का कुल योग
फिर एक प्रयोग करें: प्रतियों की संख्या में से किसी एक को बदलकर "unknown" कर दें और फ़ाइल को दोबारा चलाएँ। अब dtypes क्या कहता है, और कुल योग का क्या हुआ?
वे इस अध्याय के सबसे मूल्यवान पाँच मिनट हैं। एक सेल में एक शब्द पूरे कॉलम के प्रकार को बदल देता है और बिना कोई एरर दिए गणना को बिगाड़ देता है — और वास्तविक डेटा में ऐसा अक्सर होता रहता है।
Step 6 of 6
चुनौती — the chapter quiz
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
Sign in to take the quiz