अध्याय 03

CSV फ़ाइल पढ़ना, और पढ़ने के बाद जांचना

read_csv से फ़ाइल पढ़ना और तुरंत shape, head, info व describe से उसकी जांच करना — क्योंकि गलत पढ़ी गई फ़ाइल बिना किसी एरर के गलत उत्तर देती है।

30 मिनटPython 3.12
  1. 1समस्या
  2. 2समझें
  3. 3उदाहरण
  4. 4अनुमान
  5. 5स्वयं करें
  6. 6चुनौती

वह समस्या जिसे हम हल कर रहे हैं

अब तक टेबल की प्रत्येक वैल्यू कोड में हाथ से टाइप की गई थी। तीन पंक्तियों के लिए यह तरीका ठीक काम करता है।

वास्तविक डेटा कोड में नहीं रहता। यह किसी फ़ाइल में रहता है — किसी द्वारा ईमेल किया गया, किसी सिस्टम से निर्यात किया गया, या किसी स्प्रेडशीट से सहेजा गया। और उस फ़ाइल में बारह पंक्तियाँ नहीं बल्कि बारह हज़ार पंक्तियाँ होती हैं।

वह फ़ाइल आमतौर पर ऐसी दिखती है: सादा टेक्स्ट, पहली पंक्ति में कॉलम के नाम, और फिर प्रति पंक्ति एक रिकॉर्ड, कॉमा द्वारा अलग किया हुआ:

text
product,quantity,price
pen,12,15.0
notebook,5,60.0

इसे CSV कहते हैं — comma-separated values (अल्पविराम से अलग किए गए मान)। इसे टेबल में बदलना पांडास की केवल एक लाइन का काम है, और यह पांडास में सबसे ज़्यादा इस्तेमाल होने वाली लाइन है।

लेकिन उस लाइन के ठीक बाद बनाने लायक एक आदत है, और वही इस अध्याय का मुख्य विषय है: फ़ाइल पढ़ने के तुरंत बाद, उसे देखें। कितनी पंक्तियाँ आईं, क्या कॉलम के नाम वही हैं जिनकी आप उम्मीद कर रहे थे, क्या संख्यात्मक कॉलम वास्तव में संख्याओं के रूप में आए हैं। यदि आप उन तीस सेकंडों को छोड़ देते हैं, तो ग़लती बहुत बाद में सामने आती है, जब कोई उत्तर ग़लत होता है और कोई एरर भी नहीं आया होता।

इस अध्याय के अंत में आप कर पाएंगे

  • pd.read_csv() से फ़ाइल पढ़ना और आने वाली पाथ संबंधी समस्याओं को संभालना
  • head(), tail(), shape और columns से किसी फ़ाइल की तुरंत जाँच करना
  • पंक्ति गणना, खाली सेल और प्रत्येक कॉलम के प्रकार को एक साथ देखने के लिए info() को पढ़ना
  • describe() के साथ संख्यात्मक कॉलमों का सारांश देखना
  • FileNotFoundError और ग़लत विभाजक (separator) को पहचानना और ठीक करना

ज़रूरी शर्तें: Series और DataFrame — पांडास की दो मुख्य चीज़ें।


पहले फ़ाइल बनाएँ

अपने प्रोजेक्ट फ़ोल्डर में, ठीक इन छह पंक्तियों के साथ sales.csv नामक एक फ़ाइल बनाएँ:

text
product,quantity,price
pen,12,15.0
notebook,5,60.0
bag,2,850.0
bottle,7,120.0
eraser,30,8.0

पहली पंक्ति डेटा नहीं है, यह कॉलम के नाम हैं — हेडर (header)। अन्य पाँच पंक्तियाँ पाँच रिकॉर्ड्स (rows) हैं।

इसे एक पंक्ति में पढ़ना

python
import pandas as pd

sales = pd.read_csv("sales.csv")

print(sales)
text
product  quantity  price
0       pen        12   15.0
1  notebook         5   60.0
2       bag         2  850.0
3    bottle         7  120.0
4    eraser        30    8.0

उस एक लाइन ने चुपचाप तीन काम किए:

पहला, इसने पहली पंक्ति को हेडर के रूप में लिया — इसलिए product, quantity और price डेटा पंक्ति बनने के बजाय कॉलम के नाम बन गए।

दूसरा, इसने एक इंडेक्स बनाया, बाईं ओर 0 से 4 तक। वह फ़ाइल में मौजूद नहीं था।

तीसरा, और यह सबसे महत्वपूर्ण है, इसने प्रत्येक कॉलम के प्रकार का अनुमान लगाया। फ़ाइल में सब कुछ टेक्स्ट है — 12 वास्तव में दो कैरेक्टर्स हैं। पांडास ने प्रत्येक कॉलम को देखा और तय किया कि वह संख्या है या टेक्स्ट।

यह अनुमान आमतौर पर सही होता है। लेकिन जब यह ग़लत होता है, तो कोई एरर नहीं आता — और यही कारण है कि आपको इसे जाँचना चाहिए।

फ़ाइल पढ़ने के बाद जाँचने योग्य चार बातें

shape — कितना डेटा आया

python
print(sales.shape)
text
(5, 3)

पाँच पंक्तियाँ, तीन कॉलम। फ़ाइल में छह पंक्तियाँ थीं और इसमें पाँच हैं, क्योंकि हेडर डेटा पंक्ति नहीं है। यदि यह संख्या आपकी अपेक्षा से बहुत कम है, या ठीक एक अधिक है, तो यह पहला संकेत है कि कुछ ग़लत पढ़ा गया है।

head() और tail() — शुरुआत और अंत

python
print(sales.head(3))
text
product  quantity  price
0       pen        12   15.0
1  notebook         5   60.0
2       bag         2  850.0

किसी वास्तविक फ़ाइल की सभी बारह हज़ार पंक्तियों को प्रिंट करने से टर्मिनल भर जाता है और कुछ समझ नहीं आता। head() पहली कुछ पंक्तियाँ दिखाता है — यदि आप संख्या नहीं बताते हैं तो डिफ़ॉल्ट रूप से पाँच। tail() अंत में यही काम करता है, और अंत को देखना अलग से उपयोगी होता है, क्योंकि सिस्टम से एक्सपोर्ट की गई फ़ाइलों में अक्सर नीचे कोई खाली पंक्ति या कुल योग वाली पंक्ति छूट जाती है।

info() — सब कुछ एक नज़र में

python
sales.info()
text
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
 #   Column    Non-Null Count  Dtype
---  ------    --------------  -----
 0   product   5 non-null      object
 1   quantity  5 non-null      int64
 2   price     5 non-null      float64
dtypes: float64(1), int64(1), object(1)
memory usage: 252.0+ bytes

ध्यान दें कि इसे sales.info() लिखा गया है न कि print(sales.info()) — यह मेथड खुद प्रिंट करता है और कुछ नहीं लौटाता, इसलिए इसे print में लपेटने से अंत में एक अतिरिक्त None जुड़ जाता है।

फ़ाइल पढ़ने के बाद चलाने के लिए यह सबसे उपयोगी चीज़ है, क्योंकि यह दो महत्वपूर्ण तथ्यों को एक साथ रखती है:

Non-Null Count — प्रत्येक कॉलम में कितने सेल वास्तव में भरे हुए हैं। यहाँ तीनों में 5 non-null लिखा है, इसलिए कुछ भी खाली नहीं है। कहीं भी 4 non-null होने का मतलब है कि उस कॉलम में एक सेल खाली है, और वह आपकी गणना को बदल देगा।

Dtype — अनुमान किस प्रकार पर तय हुआ। quantity int64 के रूप में आई, price float64 के रूप में, product object के रूप में। हम यही चाहते थे।

(अंतिम पंक्ति पर memory usage का आँकड़ा आपकी मशीन पर भिन्न हो सकता है, और इससे कोई फ़र्क नहीं पड़ता।)

describe() — संख्यात्मक कॉलमों का सारांश

python
print(sales.describe())
text
quantity       price
count   5.00000    5.000000
mean   11.20000  210.600000
std    11.12205  360.217712
min     2.00000    8.000000
25%     5.00000   15.000000
50%     7.00000   60.000000
75%    12.00000  120.000000
max    30.00000  850.000000

यह संख्यात्मक कॉलमों को चुनता है और प्रत्येक पर आठ गणनाएँ चलाता है। product यहाँ मौजूद नहीं है, क्योंकि वह टेक्स्ट है।

यहाँ एक बात आपका ध्यान खींचनी चाहिए: price का औसत (mean) 210.6 है, जबकि 50% — माध्यिका (median) — केवल 60 है। इतना बड़ा अंतर बताता है कि एक मान बाकी सभी से बहुत ऊपर बैठा है, और max उसका नाम लेता है: 850। describe() को ऐसे ही पढ़ा जाता है — जब औसत और माध्यिका अलग होने लगें, तो समझें कि कोई बड़ा आउटलायर (outlier) मौजूद है।


पूर्ण उदाहरण

report.py:

python
import pandas as pd

sales = pd.read_csv("sales.csv")

print("Rows, columns:", sales.shape)
print()
print(sales.head(3))
print()
print("Columns   :", list(sales.columns))
print("Total qty :", sales["quantity"].sum())
print("Avg price :", round(sales["price"].mean(), 2))
text
Rows, columns: (5, 3)

    product  quantity  price
0       pen        12   15.0
1  notebook         5   60.0
2       bag         2  850.0

Columns   : ['product', 'quantity', 'price']
Total qty : 56
Avg price : 210.6

एक छोटा प्रोग्राम, लेकिन इसकी बनावट ध्यान देने योग्य है — पढ़ें, फिर जाँचें, फिर गणना करें। shape और head() गणनाएँ नहीं हैं, वे सवाल हैं: क्या मैंने सही फ़ाइल पढ़ी? क्या उतनी ही पंक्तियाँ हैं जितनी होनी चाहिए थीं?

और list(sales.columns) प्रिंट करने का एक ख़ास कारण है। लिस्ट के रूप में, प्रत्येक नाम कोट्स के अंदर आता है, इसलिए 'quantity ' जैसा नाम जिसके पीछे कोई स्पेस छूटा हो, तुरंत दिखाई दे जाता है। किसी अन्य तरीके से प्रिंट करने पर वह स्पेस अदृश्य रहता है और बाद में KeyError बनकर सामने आता है।


जब यह काम न करे

FileNotFoundError: [Errno 2] No such file or directory: 'sales.csv' पायथन वर्तमान फ़ोल्डर में देखता है और उसे यह फ़ाइल वहाँ नहीं मिली। यह पायथन कोर्स के दूसरे अध्याय जैसी ही समस्या है: टर्मिनल एक जगह है और फ़ाइल दूसरी जगह। आप कहाँ हैं यह देखने के लिए pwd चलाएँ, फ़ाइल वहाँ है या नहीं देखने के लिए dir चलाएँ, फिर cd करें। विंडोज़ पर फ़ाइल का नाम वास्तव में sales.csv.txt हो सकता है — एक्सप्लोरर में फ़ाइल नाम एक्सटेंशन चालू करें।

पूरी फ़ाइल एक ही कॉलम के रूप में आई विभाजक (separator) कॉमा नहीं है। अधिकांश यूरोप में सहेजी गई फ़ाइलें सेमीकोलन (semicolon) का उपयोग करती हैं, क्योंकि वहाँ दशमलव के लिए कॉमा का उपयोग होता है। pd.read_csv("sales.csv", sep=";") लिखें। टैब से अलग की गई फ़ाइलों के लिए, sep=" " लिखें।

संख्यात्मक कॉलम object के रूप में आया कॉलम में कहीं टेक्स्ट आ गया है — एक N/A, एक -, एक खाली सेल, या हज़ारों को अलग करने वाला कॉमा (1,200)। वास्तव में अंदर क्या है यह देखने के लिए df["col"].unique() चलाएँ; असामान्य वैल्यू आमतौर पर तुरंत दिख जाती है। इसका समाधान pd.to_numeric(df["col"], errors="coerce") है, जो किसी भी ग़ैर-संख्यात्मक चीज़ को खाली (NaN) में बदल देता है — जिसे मिसिंग डेटा वाले अध्याय में विस्तार से समझाया जाएगा।

UnicodeDecodeError फ़ाइल UTF-8 के रूप में सहेजी नहीं गई है, जो कि स्प्रेडशीट से निर्यात की गई फ़ाइलों के साथ अक्सर होता है। pd.read_csv("sales.csv", encoding="utf-8-sig") आज़माएँ, और यदि वह विफल हो जाए तो encoding="latin-1" का प्रयास करें।

डेटा की पहली पंक्ति कॉलम के नाम बन गई, हालाँकि फ़ाइल में कोई हेडर नहीं था pd.read_csv("sales.csv", header=None) लिखें और कॉलम 0, 1, 2 बन जाएँगे। उन्हें नाम देने के लिए, names=["product", "quantity", "price"] जोड़ें।

sales.info() के बाद एक अतिरिक्त None प्रिंट हुआ इसे print(sales.info()) के रूप में लिखा गया था। info() खुद प्रिंट करता है और कुछ नहीं लौटाता, इसलिए print इसके द्वारा लौटाए गए None को प्रिंट कर रहा है। केवल sales.info() लिखें।