2025, Oct 30 18:32

pandas में CSV से Excel रूपांतरण: वैज्ञानिक संकेतन व मेटाडेटा पंक्तियाँ सही करें

pandas में CSV/TXT को Excel में सही कन्वर्ट करें: वैज्ञानिक संकेतन संख्याओं की तरह रखें, मेटाडेटा पंक्तियाँ बचाएँ, to_numeric और header को सही हैंडल करें.

pandas के साथ CSV को Excel में बदलना आमतौर पर एक ही लाइन में हो जाता है—जब तक कि वैज्ञानिक संकेतन और इधर-उधर की मेटाडेटा पंक्तियाँ बीच में न आ जाएँ। एक आम परेशानी यह है कि संख्याओं जैसे दिखने वाले मान Excel में चुपचाप स्ट्रिंग बन जाते हैं, और फिर चार्टिंग जैसी आगे की प्रक्रियाएँ टूट जाती हैं। यह क्यों होता है और फ़ाइल के ऊपर की उपयोगी मेटाडेटा पंक्तियाँ बचाए रखते हुए इसे कैसे ठीक करें—यही यहाँ बताया गया है।

समस्या का न्यूनतम पुनरुत्पादन

नीचे दिया गया फ़ंक्शन .csv या .txt फ़ाइलें पढ़ता है, कॉलम को संख्याओं में बदलने की कोशिश करता है और .xlsx आउटपुट लिखता है। नतीजा ऊपर-ऊपर ठीक लगता है, पर मेटाडेटा हेडर के नीचे वाली पंक्तियों के लिए संख्याओं की जगह टेक्स्ट बन सकता है।

import pandas as pds
import os
from tkinter import filedialog as fd, messagebox as mb

def export_to_xlsx():
picked = fd.askopenfilenames(filetypes=[("Text and CSV files", "*.txt *.csv")])
if not picked:
return

for src in picked:
try:
delim = '\t' if src.lower().endswith('.txt') else ','
frame = pds.read_csv(src, sep=delim)

for field in frame.columns:
frame[field] = pds.to_numeric(frame[field], errors='ignore')

out_path = os.path.splitext(src)[0] + '.xlsx'
with pds.ExcelWriter(out_path, engine='openpyxl') as book:
frame.to_excel(book, index=False, float_format="%.3f")

except Exception as err:
mb.showerror("Error", f"Error converting file {src}: {err}")
return

mb.showinfo("Success", "All files have been converted successfully!")

export_to_xlsx()

ऐसा क्यों होता है

यदि फ़ाइल साफ-सुथरे हेडर और पंक्तियों से शुरू होती है, तो pandas आसानी से dtypes का अनुमान लगा लेता है। उदाहरण के तौर पर, ऐसे साधारण CSV में Excel में मान संख्यात्मक रहते हैं और सीधे ग्राफ़ के लिए तैयार:

Frequency,Random
5.0e+3,6.01e-4
5.0e+3,6.01e-4
5.0e+3,6.01e-4
5.0e+3,6.01e-4

लेकिन अगर फ़ाइल हेडर से पहले मनमाने मेटाडेटा से शुरू होती है, तो pandas उन कोशिकाओं को तालिका का हिस्सा मानकर पढ़ता है और भरोसेमंद तरीके से संख्यात्मक प्रकार नहीं पहचान पाता। इस संरचना पर ध्यान दें:

!Keysignth,Easdf,MYA1234,A.04.00
!Date: Thur

BEGIN CH1_DATA
Frequency,Random
5.0e+3,6.01e-4
5.0e+3,6.01e-4
5.0e+3,6.01e-4
5.0e+3,6.01e-4

मुख्य बात यह है: pds.to_numeric(..., errors='ignore') का मतलब “जो हो सके उसे बदलो और बाकी छोड़ दो” नहीं होता। यदि किसी कॉलम में कोई भी मान पार्स न हो पाए, तो उस पूरे कॉलम का रूपांतरण चुपचाप छोड़ दिया जाता है। ऊपर की पंक्तियों के साथ मिलकर नतीजा यह होता है कि कॉलम का dtype object रह जाता है और आउटपुट में टेक्स्ट लिखा जाता है। तब संख्याएँ असली संख्याएँ न होकर वैज्ञानिक संकेतन जैसी स्ट्रिंग दिखती हैं।

प्रतिनिधित्व पर एक व्यावहारिक बात भी है: मेमोरी में संख्याओं का कोई “scientific” या “regular” फ़ॉर्मेट नहीं होता—यह पढ़ते या लिखते वक्त दिखाने की बात है। प्लॉट के लिए मायने सिर्फ यह रखता है कि सेल में संख्या है या टेक्स्ट।

उपाय 1: pandas को वास्तविक हेडर पर इंगित करें

यदि हेडर हमेशा निश्चित संख्या की पंक्तियों के बाद आता है, तो pandas को बताइए कि असली हेडर पंक्ति कहाँ है। इससे DataFrame बनाते समय उससे ऊपर की सारी चीज़ें अनदेखी हो जाएँगी और संख्यात्मक अनुमान अपेक्षित रूप से काम करेगा।

import pandas as pds
import os
from tkinter import filedialog as fd, messagebox as mb

def export_to_xlsx_fixed_header():
picked = fd.askopenfilenames(filetypes=[("Text and CSV files", "*.txt *.csv")])
if not picked:
return

for src in picked:
try:
delim = '\t' if src.lower().endswith('.txt') else ','
frame = pds.read_csv(src, sep=delim, header=3) # हेडर पंक्ति सूचकांक 3 पर है

out_path = os.path.splitext(src)[0] + '.xlsx'
with pds.ExcelWriter(out_path, engine='openpyxl') as book:
frame.to_excel(book, index=False) # float_format नहीं

except Exception as err:
mb.showerror("Error", f"Error converting file {src}: {err}")
return

mb.showinfo("Success", "All files have been converted successfully!")

इससे संख्यात्मक प्रकार बने रहते हैं, लेकिन Excel फ़ाइल से मेटाडेटा पंक्तियाँ हट जाती हैं, क्योंकि read_csv हेडर से पहले की हर चीज़ छोड़ देता है।

उपाय 2: मेटाडेटा रखें और सिर्फ डेटा पंक्तियाँ बदलें

यदि आप Excel आउटपुट में ऊपर की पंक्तियाँ भी रखना चाहते हैं, तो फ़ाइल सामान्य रूप से लोड करें और केवल डेटा वाले हिस्से को संख्यात्मक प्रकार में बदलें। मेटाडेटा पंक्तियाँ छोड़ने से पहले वाला कॉलम-स्तरीय रूपांतरण विफल नहीं होगा।

import pandas as pds
import os
from tkinter import filedialog as fd, messagebox as mb

def export_to_xlsx_keep_meta():
picked = fd.askopenfilenames(filetypes=[("Text and CSV files", "*.txt *.csv")])
if not picked:
return

for src in picked:
try:
delim = '\t' if src.lower().endswith('.txt') else ','
frame = pds.read_csv(src, sep=delim) # मेटाडेटा को न छोड़ें

for field in frame.columns:
frame.loc[3:, field] = pds.to_numeric(frame[field][3:]) # पंक्ति सूचकांक 3 से परिवर्तित करें

out_path = os.path.splitext(src)[0] + '.xlsx'
with pds.ExcelWriter(out_path, engine='openpyxl') as book:
frame.to_excel(book, index=False) # float_format नहीं

except Exception as err:
mb.showerror("Error", f"Error converting file {src}: {err}")
return

mb.showinfo("Success", "All files have been converted successfully!")

इसके साथ, मेटाडेटा बना रहता है और संख्यात्मक ब्लॉक असली संख्या बन जाता है, जो प्लॉटिंग के लिए उपयुक्त है।

उपाय 3: जब मेटाडेटा की ऊँचाई स्थिर न हो

यदि मेटाडेटा पंक्तियों की संख्या बदलती रहती है, तो पहली संख्यात्मक पंक्ति को प्रोग्रामेटिक तरीके से ढूँढें और वहीं से रूपांतरण शुरू करें। एक सरल तरकीब यह है कि पहले कॉलम को तब तक स्कैन करें जब तक कोई संख्यात्मक मान न मिल जाए।

# pds.read_csv(...) से frame पढ़ने के बाद:
first_col = frame.columns[0]
for row_idx, cell in enumerate(frame[first_col]):
try:
pds.to_numeric(cell)
start_idx = row_idx
break
except ValueError:
pass
else:
print("Warning: no numeric data in the first column")
start_idx = row_idx + 1

फिर उसी पंक्ति से हर कॉलम के लिए संख्यात्मक रूपांतरण लागू करें।

for field in frame.columns:
frame.loc[start_idx:, field] = pds.to_numeric(frame[field][start_idx:])

यह तरीका मानता है कि सभी कॉलम उसी पंक्ति पर संख्यात्मक हो जाते हैं और उसके बाद कोई गैर-संख्यात्मक मान नहीं आता।

float_format के बारे में

to_excel में float_format="%.3f" देने से लिखने से पहले ही राउंडिंग मजबूर हो जाती है। इससे 6e-4 और 6.12e-4 जैसी बारीकियाँ एक जैसे प्रदर्शित मान में बदलकर छिप सकती हैं। जब आपका डेटा सचमुच संख्यात्मक हो, तो नंबर फ़ॉर्मेटिंग Excel पर छोड़ दें।

यह क्यों मायने रखता है

Excel में चार्ट, एग्रीगेशन और फ़ॉर्मूले असली संख्यात्मक प्रकारों पर निर्भर करते हैं। यदि डेटा स्ट्रिंग के रूप में संग्रहीत हो, तो प्लॉट या तो असफल हो जाते हैं या चुपचाप गलत परिणाम दे देते हैं। पढ़ने के चरण को सही करना—वास्तविक हेडर की ओर संकेत करके या केवल डेटा क्षेत्र को बदलकर—अस्पष्टता हटाता है और संख्यात्मक अखंडता बनाए रखता है।

समापन

लक्षण फ़ॉर्मेटिंग की दिक्कत जैसे लग रहे थे, पर असल वजह हेडर से पहले मिला-जुला कंटेंट और उदार रूपांतरण फ़्लैग था। भरोसेमंद रास्ता है या तो pandas को बताना कि हेडर कहाँ से शुरू होता है, या केवल उन्हीं पंक्तियों को बदलना जो डेटा सेट का हिस्सा हैं। एक्सपोर्ट के दौरान पहले से राउंडिंग करने से बचें। इन समायोजनों के साथ, वैज्ञानिक संकेतन सही संख्याओं की तरह पार्स होता है और Excel एवं चार्ट में अपेक्षित तरीके से व्यवहार करता है।

यह लेख StackOverflow पर एक प्रश्न (लेखक: julien1h) और joanis के उत्तर पर आधारित है।