Written and maintained by CASRAI Editorial Board
Last updated
numpy.loadtxt reads a plain-text file, such as a CSV, a tab-separated export or a whitespace-aligned instrument dump, and returns a NumPy array. The NumPy manual describes it as a function that “aims to be a fast reader for simply formatted files”. This guide covers the arguments you will actually use, shows the documented examples with their output, and sets out when to switch to numpy.genfromtxt instead. It also records which behaviours changed between NumPy versions, because many tutorials still describe the older ones.
What numpy.loadtxt is used for in research
Research data often arrives as a text file: a plate-reader export, a sensor log, a table of simulation output, or a CSV saved from a spreadsheet. When every row has the same number of values and nothing is missing, loadtxt turns that file into an array in one call, ready for plotting or numerical analysis. The same function accepts a file object, a path string, a pathlib.Path, a list of strings or a generator, and if the file name ends in .gz or .bz2 the file is decompressed first.
Instrument and lab files often begin with comment-prefixed metadata lines. By default loadtxt treats everything after a # as a comment, and skiprows lets you drop a fixed number of leading lines (comments included) before parsing begins. If you are still deciding how to clean data before analysis, see the CASRAI guides on data cleaning steps and data wrangling.
Install or access
loadtxt ships with NumPy, so installing NumPy is all that is needed. The NumPy installation page gives these routes:
- pip:
pip install numpy - conda:
conda create -n my-env, thenconda activate my-env, thenconda install numpy - virtual environment:
python -m venv my-env, thensource my-env/bin/activateon macOS or Linux (my-env\Scripts\activateon Windows), thenpip install numpy
To confirm the install, run import numpy as np; print(np.__version__). The version matters here, because the default for encoding changed in NumPy 2.0 (see the version table below).
Step-by-step: load a text file into an array
The signature in the current NumPy manual is:
numpy.loadtxt(fname, dtype=float, comments='#', delimiter=None, converters=None,
skiprows=0, usecols=None, unpack=False, ndmin=0, encoding=None,
max_rows=None, *, quotechar=None, like=None)
- Import NumPy.
import numpy as np - Point to the file. Pass the path as
fname. The documentation examples useio.StringIOso they run without a file:from io import StringIO, thenc = StringIO("0 1\n2 3"). - Call loadtxt.
np.loadtxt(c)returnsarray([[0., 1.], [2., 3.]]). The default delimiter is whitespace, so a comma-separated file needsdelimiter=','. - Select columns and unpack. With
c = StringIO("1,0,2\n3,0,4"), the callx, y = np.loadtxt(c, delimiter=',', usecols=(0, 2), unpack=True)givesx = array([1., 3.])andy = array([2., 4.]). Columns are numbered from 0.unpack=Truetransposes the result so that each column lands in its own variable. - Skip headers. Set
skiprows=1to skip a one-line header. The manual states thatskiprowsskips the first lines, including comments. - Limit the rows.
max_rowsreads that many rows of content after the skipped lines. Empty lines and comment lines are not counted towardsmax_rows.
Output and how to read it
By default the result is a floating-point array: dtype defaults to float. A file with several columns gives a two-dimensional array with one row per line. ndmin accepts 0, 1 or 2 and sets the minimum number of dimensions; with the default of 0, single-valued axes are squeezed away.
For mixed text and numbers, pass a structured dtype. The manual’s example reads “M 21 72” and “F 35 58” with dtype={'names': ('gender', 'age', 'weight'), 'formats': ('S1', 'i4', 'f4')} and returns array([(b'M', 21, 72.), (b'F', 35, 58.)], dtype=[('gender', 'S1'), ('age', '<i4'), ('weight', '<f4')]). With a structured dtype the result is one-dimensional, each row is one record, and the number of columns used must match the number of fields.
Because the result is a NumPy array, it can go straight into plotting code; the CASRAI guide on importing matplotlib.pyplot as plt covers that import, and Python for exploratory data analysis shows where array loading sits in a wider workflow.
Version notes: what changed and when
Several defaults have moved across NumPy releases. The table below is taken from the “Changed in version” notes in the manual.
| Argument | What the manual says |
|---|---|
encoding |
Default is None, which uses the system default. Before NumPy 2.0 the default was 'bytes' for Python 2 compatibility. |
delimiter |
Only single-character delimiters are supported (changed in 1.23.0). Newline characters cannot be the delimiter. |
converters |
Passing a single callable to apply to all columns was added in 1.23.0. |
max_rows |
From 1.23.0, lines containing no data, including comment lines, are not counted towards max_rows, although they still count in skiprows. |
quotechar |
Quoting support is off by default (quotechar=None); the argument was introduced in 1.23.0. |
Quoted fields and converters
If a text field contains the delimiter or the comment character, set quotechar. Inside a quoted item, delimiter and comment characters are ignored, and two consecutive quote characters inside a quoted field mean the first is an escape character. The manual’s example reads '"alpha, #42", 10.0\n"beta, #64", 2.0\n' with dtype=np.dtype([("label", "U12"), ("value", float)]), delimiter="," and quotechar='"'.
The converters argument preprocesses text before parsing. It can be a dictionary mapping column numbers to functions, or, since 1.23.0, a single callable applied to every column. The manual shows {0: lambda x: np.floor(float(x)), 1: lambda x: np.ceil(float(x))} turning “1.618, 2.296” and “3.141, 4.669” into array([[1., 3.], [3., 5.]]), a trailing-minus converter that turns “31.25-” into -31.25, and a converter that parses hexadecimal values with functools.partial(int, base=16) so that “0xDE 0xAD” becomes [222., 173.].
Troubleshooting
- Rows with different numbers of values. The manual states that each row must have the same number of values to read all of them. If the rows are uneven, a subset of up to n columns, where n is the smallest count of values on any row, can be read by naming columns with
usecols. The manual’s example,StringIO("1 2\n2 4\n3 9 12\n4 16 20")withusecols=(0, 1), returns a four-row, two-column array. - Delimiter errors. A multi-character delimiter is not supported in current NumPy (single characters only). Re-save the file with a single-character separator or pre-process the lines.
- Text appearing as bytes or garbled. Set
encodingexplicitly. The manual notes thatencoding='bytes'turns on backward-compatibility workarounds that return byte arrays; override it to receive unicode arrays and pass strings to converters. - Header lines or leading metadata. Use
skiprowsfor a fixed number of lines, or leave the defaultcomments='#'to ignore comment-prefixed lines. - Missing values.
loadtxtis not designed for gaps. Usegenfromtxt(next section), and see the CASRAI guide on numpy.nan for how missing values are represented once loaded.
loadtxt vs genfromtxt
The loadtxt manual page says genfromtxt “provides more sophisticated handling of, e.g., lines with missing values”, and the genfromtxt page describes loadtxt as the “equivalent function when no data is missing”. Both pages are sourced below.
| Question | numpy.loadtxt | numpy.genfromtxt |
|---|---|---|
| What is it for? | A fast reader for simply formatted files | Loading text with missing values handled as specified |
| Name of the leading-lines argument | skiprows |
skip_header (it also has skip_footer) |
| Missing data | Not handled; every row needs the same number of values | missing_values sets the strings that mean missing, filling_values sets the defaults to use |
| Field names | Through a structured dtype |
names=True takes names from the first line after skip_header, or pass a list of names |
| Row limit | max_rows |
max_rows |
The manual’s genfromtxt example reads one line, "1,1.3,abcde", with dtype=None, names=['myint', 'myfloat', 'mystring'] and delimiter=",". The argument name skip_header differs from skiprows, so code cannot be switched between the two functions by changing only the name.
Free alternatives
NumPy and everything listed here are free to use. The “See also” list on the loadtxt manual page names these related functions:
| Function | Where it is documented |
|---|---|
numpy.genfromtxt |
Text files with missing values; compared in the table above |
numpy.load |
Listed under See also on the loadtxt page |
numpy.fromstring |
Listed under See also on the loadtxt page |
numpy.fromregex |
Listed under See also on the loadtxt page |
scipy.io.loadmat |
Listed under See also on the loadtxt page |
For a text format specifically, the CASRAI guide on what a TSV file is explains the tab-separated case, which loadtxt reads with delimiter='\t'.
FAQ
How do I read a CSV file with numpy.loadtxt?
Pass the file name and set delimiter=',', because the default delimiter is whitespace. Add skiprows=1 if the first line is a header.
What is the difference between loadtxt and genfromtxt?
loadtxt is the fast reader for simply formatted files and needs the same number of values on every row. genfromtxt handles missing values through missing_values and filling_values, and it names its header argument skip_header.
How do I load only some columns?
Use usecols with zero-based column numbers, for example usecols=(0, 2). Add unpack=True to receive each column as a separate array.
Does loadtxt handle quoted text containing commas?
Yes, once quoting is turned on with quotechar='"'. Quoting is off by default, and the argument was added in NumPy 1.23.0.
Sources
- NumPy manual, numpy.loadtxt, checked 2026-10-29.
- NumPy manual, numpy.genfromtxt, checked 2026-10-29.
- NumPy, Installing NumPy, checked 2026-10-29.








