NumPy Count Substrings with strings.count() and char.count()

Quick answer: For current NumPy string arrays, np.strings.count(array, sub) returns one integer count per element. It counts literal, non-overlapping occurrences and accepts start and end ranges. Use the result as a mask when filtering; use np.count_nonzero for the number of true or nonzero array entries, which is a different operation.

Python Pool infographic showing NumPy strings.count substring arrays start end ranges non-overlapping matches and masks
Use numpy.strings.count for current NumPy string arrays, remember matches are non-overlapping, and turn the integer result into a mask when filtering.

NumPy count usually means counting how many times a substring appears inside every string element of a NumPy array. The old article used outdated links and treated this as only np.char.count(). Current NumPy documentation is clearer: modern string operations live under numpy.strings, and numpy.strings.count is the current API for this job. The older numpy.char.count function is still documented, but the numpy.char module is described as legacy in the stable manual.

What NumPy count does

np.strings.count(a, sub, start=0, end=None) returns an array with the number of non-overlapping occurrences of sub in each string element of a. The result has the same shape as the input string array, but its values are integers. This is different from NumPy count_nonzero(), which counts nonzero or true values in an array. Use strings.count for substring matches; use count_nonzero for boolean masks and numeric arrays.

Here is the simplest modern form. Each element is checked separately, so the output has one count per input string.

import numpy as np

words = np.array(["python", "pythonic", "data"])
counts = np.strings.count(words, "py")
print(counts)

Syntax and parameters

The main arguments are a, the string array, and sub, the substring to search for. The optional start and end arguments limit the search to a slice inside each string, using the same half-open idea as normal Python slicing: start is included and end is excluded. The function accepts arrays of strings or bytes, and the substring can also be array-like when you need element-wise matching.

One detail matters: matches are non-overlapping. In a word such as banana, counting ana returns one match, not two overlapping matches.

import numpy as np

values = np.array(["banana", "bandana", "cabana"])
print(np.strings.count(values, "ana"))

Python Pool infographic showing a string, substring, characters, positions, and count operation
Text input: A string, substring, characters, positions, and count operation.

Using start and end

The range arguments are useful when your strings have prefixes, fixed-width codes, or suffixes that should not be searched. For example, if the first character is a status marker or the final characters are a checksum, you can count only the meaningful part of each value. This keeps the operation vectorized while avoiding manual loops.

import numpy as np

codes = np.array(["AB-100-AB", "AB-200", "XY-300-AB"])
print(np.strings.count(codes, "AB", start=1, end=8))

strings.count vs char.count

For new code on current NumPy, prefer np.strings.count. If you maintain older code or support older NumPy versions, you will still see np.char.count. The call shape is almost the same, so migration is usually straightforward: replace np.char.count with np.strings.count after confirming your NumPy version supports the newer namespace.

import numpy as np

labels = np.array(["error:error", "warning", "error"])
modern = np.strings.count(labels, "error")
legacy = np.char.count(labels, "error")
print(modern)
print(legacy)

This distinction is important for SEO and maintenance because older tutorials often point only to numpy.char. That can still help readers understand existing code, but a refreshed article should explain the modern namespace instead of teaching a legacy module as the only path.

Counting in two-dimensional arrays

Because the function is vectorized, it works across arrays of any shape. If your data is a table of labels, product names, log messages, or short text fields, NumPy returns a count for each cell. You do not need nested Python loops for basic substring counting.

import numpy as np

table = np.array([
    ["red apple", "green apple"],
    ["apple pie", "berry tart"],
])
print(np.strings.count(table, "apple"))
Python Pool infographic mapping a substring through non-overlapping matches and an integer count
Count matches: A substring through non-overlapping matches and an integer count.

Filtering with the result

The returned count array can be turned into a boolean mask. This is useful when you want to keep rows or messages that contain a substring at least once. For numeric summaries of the mask, combine this with np.count_nonzero; for averages after filtering, see the NumPy mean guide.

import numpy as np

messages = np.array(["fail fail", "ok", "fail soon"])
counts = np.strings.count(messages, "fail")
needs_review = counts > 0
print(messages[needs_review])

When it is the right tool

Use this function when the strings are already in a NumPy array and you want an element-wise answer without changing shape. It is a good fit for compact labels, product codes, log fragments, small text fields, and prepared arrays in a data-cleaning step. It is not a text-search engine, and it is not meant for long documents. For large natural-language text, parse the data first and use a tool designed for tokenization or pattern matching.

Python Pool infographic comparing Python str count, NumPy strings count, char count, and vectorization
String arrays: Python str count, NumPy strings count, char count, and vectorization.

Common mistakes

Do not use numpy.count; NumPy does not have a top-level substring-counting function with that name. Do not expect overlapping matches. Do not use this for regular expressions, because the substring is treated literally. If you need regex matching, use Python string tools, pandas string methods, or the re module depending on the shape of your data. If you only need to search a normal Python list of strings, our find string in list guide may be simpler than converting the data to NumPy.

Use NumPy substring counting when the data is already in an array and you want a vectorized result that keeps the same shape. Use plain Python when the data is small or not already array-based. That distinction keeps the code readable and avoids adding NumPy where it does not help.

Count Each String Element

The operation is element-wise and preserves the input shape. This makes it useful for compact labels, codes, and log fragments already represented as a NumPy string array, without writing a nested Python loop.

import numpy as np

values = np.array(["python", "pythonic", "data"])
counts = np.strings.count(values, "py")
print(counts)

Remember Matches Are Non-overlapping

Substring matches do not overlap. If a substring can overlap with itself, do not infer a regex-style overlapping count from this API; define the desired text rule explicitly and use a tool that supports it.

import numpy as np

values = np.array(["banana", "bandana"])
print(np.strings.count(values, "ana"))
Python Pool infographic testing empty substring, overlap, case, Unicode, start, and stop
Text checks: Empty substring, overlap, case, Unicode, start, and stop.

Limit The Search Range

start and end behave like slice boundaries for each string. Use them when a prefix, suffix, or fixed-width field should not participate in the count, and keep the range policy visible in the code so it is not mistaken for a whole-string search.

import numpy as np

values = np.array(["AB-100-AB", "AB-200"])
print(np.strings.count(values, "AB", start=1, end=8))

Turn Counts Into A Filter

The integer result can become a boolean mask for selecting values with at least one match. If you need the number of matching elements rather than the count within each string, count the mask separately with count_nonzero.

import numpy as np

messages = np.array(["fail fail", "ok", "fail soon"])
counts = np.strings.count(messages, "fail")
matching = messages[counts > 0]
print(matching)
print(np.count_nonzero(counts > 0))

NumPy’s official strings.count reference documents the non-overlapping behavior and range arguments. For the older namespace, compare char.count, and use count_nonzero for boolean or numeric array counts.

For related matching and array counts, compare count_nonzero(), NumPy isin(), and Python character searches when deciding whether the task is substring counting or element membership.

Frequently Asked Questions

How do I count a substring in a NumPy array?

Use np.strings.count(array, substring) in current NumPy versions; it returns one integer count for each string element.

Does NumPy count overlapping matches?

No. The count is based on non-overlapping occurrences, matching the behavior documented for the string operation.

What are start and end used for?

They limit the search to a slice-like range inside each string, which is useful when prefixes or suffixes should be ignored.

What is the difference between strings.count and char.count?

strings.count is the current namespace for new code, while char.count is the older API you may need to maintain for older NumPy environments.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted