CSV ফাইল পড়া, আর পড়ার পর যাচাই করা
read_csv দিয়ে ফাইল পড়া এবং সাথে সাথেই shape, head, info আর describe দিয়ে দেখে নেওয়া — কারণ ভুল পড়া ফাইল কোনো ত্রুটি ছাড়াই ভুল উত্তর দেয়।
কীভাবে শিখতে চান?
যে সমস্যাটা আমরা সমাধান করছি
এতক্ষণ টেবিলের প্রতিটি মান আমরা নিজের হাতে কোডে লিখেছি। তিন সারির জন্য সেটা চলে।
বাস্তবে ডেটা কোডে থাকে না। সেটি থাকে একটি ফাইলে — কেউ ইমেইলে পাঠিয়েছেন, কোনো সিস্টেম থেকে এক্সপোর্ট হয়েছে, বা এক্সেল থেকে সেভ করা হয়েছে। আর ফাইলটির সারি বারোটা নয়, বারো হাজার।
সেই ফাইলটির চেহারা সাধারণত এরকম — সাদামাটা লেখা, প্রথম লাইনে কলামের নাম, তারপর প্রতি লাইনে একটি করে সারি, কমা দিয়ে আলাদা করা:
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আর ভুল বিভাজকের সমস্যা চিনে ঠিক করতে
আগে যা জানা লাগবে: Series আর DataFrame — পান্ডাসের দুটি জিনিস।
ফাইলটি তৈরি করে নিন
প্রজেক্ট ফোল্ডারে sales.csv নামে একটি ফাইল বানান, আর ঠিক এই ছয়টি লাইন লিখুন:
product,quantity,price
pen,12,15.0
notebook,5,60.0
bag,2,850.0
bottle,7,120.0
eraser,30,8.0প্রথম লাইনটি ডেটা নয়, কলামের নাম — একে বলে হেডার। বাকি পাঁচটি লাইন পাঁচটি সারি।
এক লাইনে পড়া
import pandas as pd
sales = pd.read_csv("sales.csv")
print(sales)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 — কত এলো
print(sales.shape)(5, 3)পাঁচ সারি, তিন কলাম। ফাইলে ছয় লাইন ছিল, এখানে পাঁচ সারি — কারণ হেডারটি সারি নয়। সংখ্যাটি যদি প্রত্যাশার চেয়ে অনেক কম বা এক বেশি হয়, সেটিই প্রথম সংকেত যে কিছু একটা ভুল পড়া হয়েছে।
head() আর tail() — শুরু ও শেষ
print(sales.head(3))product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0বারো হাজার সারির ফাইল পুরোটা ছাপালে টার্মিনাল ভরে যাবে আর কিছুই বোঝা যাবে না। head() প্রথম কয়েকটি দেখায় — সংখ্যা না দিলে পাঁচটি। tail() একইভাবে শেষেরগুলো, আর শেষটা দেখা আলাদাভাবে কাজের, কারণ এক্সপোর্ট করা ফাইলের শেষে প্রায়ই একটি ফাঁকা বা যোগফলের সারি জুড়ে থাকে।
info() — একনজরে সবকিছু
sales.info()<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() — সংখ্যার কলামগুলোর সারসংক্ষেপ
print(sales.describe())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% — অর্থাৎ মধ্যমা — মাত্র 60। এতটা ফারাকের মানে একটি মান বাকিদের থেকে অনেক বড়, আর max সেটি দেখিয়েও দিচ্ছে: 850। এভাবেই describe() পড়া হয় — গড় আর মধ্যমা দূরে সরে গেলে সেখানে তাকাতে হয়।
একটা সম্পূর্ণ উদাহরণ
report.py:
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))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 হয়ে যাওয়াও একটি সম্ভাবনা — এক্সপ্লোরারে এক্সটেনশন দেখানো চালু করে নিন।
পুরো ফাইলটি এক কলামে চলে এসেছে বিভাজকটি কমা নয়। ইউরোপে সেভ করা ফাইলে প্রায়ই সেমিকোলন থাকে, কারণ সেখানে দশমিকের জন্য কমা ব্যবহৃত হয়। pd.read_csv("sales.csv", sep=";") লিখুন। ট্যাব দিয়ে আলাদা করা হলে sep="\t"।
সংখ্যার কলামটি object হয়ে এসেছে কলামটির কোথাও একটি লেখা ঢুকে আছে — একটি N/A, একটি -, একটি ফাঁকা ঘর, বা হাজারের কমা (1,200)। df["col"].unique() চালিয়ে দেখুন ভেতরে কী কী আছে; অদ্ভুত মানটি সাধারণত চোখেই পড়ে যায়। ঠিক করার উপায় pd.to_numeric(df["col"], errors="coerce"), যা যা সংখ্যা নয় তাকে ফাঁকা বানিয়ে দেয় — অনুপস্থিত মানের অধ্যায়ে এটি বিস্তারিত আসবে।
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() লিখুন।
ধাপ ৪ / ৬ — অনুমান
যাচাই করুন
ফাইলটিতে ছয়টি লাইন আছে। shape কী বলবে?
from io import StringIO
import pandas as pd
# Stands in for sales.csv, so this snippet runs on its own.
RAW = """product,quantity,price
pen,12,15.0
notebook,5,60.0
bag,2,850.0
bottle,7,120.0
eraser,30,8.0
"""
sales = pd.read_csv(StringIO(RAW))
print(sales.shape)- A(5, 3)
- B(5, 4)
- C(3, 5)
- D(6, 3)
info()-এর Non-Null Count কলামটি কী বলে?
- Aপ্রতিটি কলামে কয়টি ঘর সত্যিই ভরা — সংখ্যাটি সারির মোট সংখ্যার চেয়ে কম হলে সেখানে ফাঁকা ঘর আছে
- Bপ্রতিটি কলামে কয়টি ঘর ফাঁকা
- Cপ্রতিটি কলাম কত জায়গা নিচ্ছে
- Dপ্রতিটি কলামে কয়টি আলাদা মান আছে
ফাইলটি সেমিকোলন দিয়ে আলাদা করা, কিন্তু sep দেওয়া হয়নি। কী ছাপা হবে?
from io import StringIO
import pandas as pd
# Stands in for sales.csv, so this snippet runs on its own.
RAW = """product;quantity
pen;12
notebook;5
"""
df = pd.read_csv(StringIO(RAW))
print(df.shape)
print(list(df.columns))- A(3, 1) ['product;quantity']
- B(2, 1) ['product;quantity']
- C(2, 2) ['product', 'quantity']
- Dএকটি `ParserError`
উত্তর দিতে অ্যাকাউন্ট লাগবে
উত্তর মিলিয়ে দেখতে সাইন ইন করুন
প্রশ্নগুলো উপরে আছে, আর মাথায় মাথায় উত্তর ভেবে নেওয়াই আসল কাজ। সঠিক উত্তর, ব্যাখ্যা আর তিন ধাপের ইঙ্গিত দেখতে সাইন ইন করুন।
নিজে করুন
students.csv নামে একটি ফাইল বানান, যাতে অন্তত আটজনের তথ্য থাকবে — নাম, বয়স, আর একটি নম্বর, তিনটি কলামে।
তারপর report.py লিখুন, যা:
- ফাইলটি পড়বে
shapeআরlist(columns)ছাপাবেhead(3)আরtail(2)ছাপাবেinfo()চালাবে এবং তিনটি কলামের ধরন ঠিক আছে কি না বলবেdescribe()ছাপাবে, আর নম্বরের কলামের গড় ও সর্বোচ্চ আলাদা করে দেখাবে
তারপর ইচ্ছে করে ভাঙুন — তিনবার, আর প্রতিবার কী ঘটল সেটি খেয়াল করুন:
- নম্বরের কলামের একটি ঘরে
N/Aলিখে দিন।info()-এরDtypeকী বলছে এখন? গড়ের হিসাবটির কী হলো? - ফাইলটির কমাগুলো সেমিকোলন দিয়ে বদলে দিন।
shapeএখন কী বলছে, আর কেন? - প্রথম লাইনটি, অর্থাৎ হেডারটি মুছে দিন। কয় সারি এলো, আর কলামের নাম এখন কী?
তিনটিই বাস্তবে নিয়মিত ঘটে, আর তিনটিরই একটি করে স্পষ্ট লক্ষণ আছে। আজ ইচ্ছে করে ঘটিয়ে সেই লক্ষণগুলো চিনে রাখলে পরের বার ফাইলটি দেখেই বুঝে যাবেন কী হয়েছে।
ধাপ ৬ / ৬
কঠিন করা — অধ্যায়ের কুইজ
সহজ থেকে কঠিন — দশটি প্রশ্ন, শেষেরগুলো ইচ্ছে করেই কঠিন।
সাইন ইন করে কুইজ দিন