Text Files: savetxt, loadtxt, genfromtxt
Write arrays to CSV/text with np.savetxt and read them with np.loadtxt (clean numeric data) or np.genfromtxt (missing values, headers, mixed columns).
Most real data arrives as CSV — a scorecard exported from Excel, a stats file from a cricket website. CSV is plain text: humans can read it and every tool understands it. NumPy can write and read such files directly.
Definition
np.savetxtwrites a 1D or 2D array to a text file, one row per line, values separated by a delimiter and formatted with a format string.
np.loadtxtreads a text file of clean, complete numeric data into an array. It fails if a value is missing or not a number.
np.genfromtxtis the forgiving reader: it handles missing values (filling them withnan), header rows, column names and mixed types.
- Delimiter — the character between values:
","for CSV,"\t"for TSV, whitespace by default. - Format string (
fmt) — printf-style:"%d"integer,"%.2f"2 decimals,"%s"string. Default is"%.18e"(scientific notation, 18 digits). nan— "Not a Number", NumPy's float marker for missing data. Usenp.isnan,np.nanmean,np.nansumto work with it.
Syntax
python
np.savetxt(fname, X, fmt="%.18e", delimiter=" ", header="", comments="# ")
np.loadtxt(fname, dtype=float, delimiter=None, skiprows=0, usecols=None)
np.genfromtxt(fname, dtype=float, delimiter=None, skip_header=0, usecols=None,
names=None, filling_values=None, encoding=None)| Function | Parameter | Meaning | Default |
|---|---|---|---|
savetxt | fname, X | File name / file object, and the 1D/2D array | — required |
savetxt | fmt | Format of each value | "%.18e" |
savetxt | delimiter | String between columns | " " |
savetxt | header | Text written on the first line | "" |
savetxt | comments | Prefix added before the header | "# " |
loadtxt | dtype | Type of the result | float |
loadtxt | delimiter | Column separator | None → any whitespace |
loadtxt | skiprows | Lines to skip at the top (e.g. header) | 0 |
loadtxt / genfromtxt | usecols | Which columns to read, e.g. (1, 2) | None → all |
genfromtxt | skip_header | Lines to skip at the top | 0 |
genfromtxt | names | True → use the first line as column names (structured array) | None |
genfromtxt | filling_values | What to put in missing cells | nan for floats |
The playground has no disk, so the examples use io.StringIO — an in-memory text file. On your computer just pass a file name like "scores.csv".
Example — savetxt: write a CSV
python
import numpy as np
import io
scores = np.array([[72, 45, 88], [56, 0, 74]])
buf = io.StringIO()
np.savetxt(buf, scores, fmt="%d", delimiter=",", header="m1,m2,m3", comments="")
print(buf.getvalue())text
m1,m2,m3
72,45,88
56,0,74How it works: fmt="%d" writes whole numbers, delimiter="," makes it a CSV, and comments="" stops NumPy from writing # in front of the header (Excel would otherwise show # m1). Without fmt, the default is ugly scientific notation:
python
buf = io.StringIO()
np.savetxt(buf, np.array([[0.5, 1.25], [2.0, 3.333]]))
print(buf.getvalue())
buf2 = io.StringIO()
np.savetxt(buf2, np.array([[0.5, 1.25], [2.0, 3.333]]), fmt="%.2f", delimiter=",")
print(buf2.getvalue())text
5.000000000000000000e-01 1.250000000000000000e+00
2.000000000000000000e+00 3.333000000000000185e+00
0.50,1.25
2.00,3.33Example — loadtxt: read clean numeric data
python
csv = io.StringIO("""m1,m2,m3
72,45,88
56,0,74
45,32,0""")
data = np.loadtxt(csv, delimiter=",", skiprows=1, dtype=int)
print(data)
print("per match totals:", data.sum(axis=0))text
[[72 45 88]
[56 0 74]
[45 32 0]]
per match totals: [173 77 162]skiprows=1 skips the header text (loadtxt can't turn "m1" into a number); dtype=int gives integers instead of the default floats.
Example — genfromtxt: missing values
python
csv = io.StringIO("""player,runs,balls
Virat,72,48
Rohit,,30
Hardik,45,NA""")
data = np.genfromtxt(csv, delimiter=",", skip_header=1, usecols=(1, 2))
print(data)
print("missing values:", np.isnan(data).sum())
print("mean runs ignoring NaN:", np.nanmean(data[:, 0]))text
[[72. 48.]
[nan 30.]
[45. nan]]
missing values: 2
mean runs ignoring NaN: 58.5Rohit's empty runs cell and Hardik's NA balls both became nan. np.nanmean skips them: (72 + 45) / 2 = 58.5. The same file with loadtxt crashes:
text
ValueError: could not convert string '' to float64 at row 1, column 2.Example — text columns and named columns
python
csv = io.StringIO("""player,runs,balls
Virat,72,48
Rohit,56,30
Hardik,45,25""")
names = np.genfromtxt(csv, delimiter=",", skip_header=1, usecols=0, dtype=str)
print(names)
csv.seek(0)
nums = np.genfromtxt(csv, delimiter=",", names=True, dtype=None, encoding="utf-8")
print(nums["runs"], nums.dtype.names)text
['Virat' 'Rohit' 'Hardik']
[72 56 45] ('player', 'runs', 'balls')dtype=str reads a text column. names=True + dtype=None creates a structured array whose columns you access by name — at this point, though, Pandas (pd.read_csv) is usually the better tool, and it is the next course.
Comparison — loadtxt vs genfromtxt
np.loadtxt | np.genfromtxt | |
|---|---|---|
| Missing values | ❌ raises ValueError | ✅ become nan (or filling_values) |
| Skip header | skiprows= | skip_header= |
| Column names | no | names=True |
| Mixed types | limited | dtype=None guesses per column |
| Speed | faster | slower |
| Use when | data is clean and numeric | data is messy or has gaps |
Common mistakes
- ❌
loadtxton a file with a header row →ValueError: could not convert string 'm1' to float64 at row 0, column 1.✅skiprows=1. - ❌ Forgetting
delimiter=","for a CSV — the default splits on whitespace, so a whole line becomes one "value". ✅ Always set the delimiter. - ❌
np.meanon data withnan→ result isnan. ✅np.nanmean,np.nansum,np.nanmax. - ❌
savetxton a 3D array → error. ✅ Reshape to 2D first or usenp.save.
Interview tip
Q: When would you use np.genfromtxt instead of np.loadtxt?
A: When the file has missing or non-numeric entries, a header you want as column names, or mixed column types. loadtxt is faster but only handles clean, complete numeric data.
Key points to remember
- np.savetxt writes a 1D/2D array as text; set fmt (e.g. '%d', '%.2f') and delimiter=',' for a CSV.
- Pass comments='' so the header line isn't prefixed with '# '.
- np.loadtxt reads clean numeric text; use skiprows for headers and dtype=int for integers.
- np.genfromtxt handles missing values (as nan), headers (skip_header), names=True and mixed types.
- Use np.isnan, np.nanmean and np.nansum to work with missing values.
- usecols picks columns; dtype=str reads text columns.
- In the playground io.StringIO stands in for a real text file.
Try it yourself
Write a scorecard CSV
Read clean vs messy CSV
Practice: fill missing values
Revision Flashcards
Tap a card to flip it and see the answer.
