AttributeError: Can only use .str accessor with string values

avatar
Borislav Hadzhiev

Last updated: Apr 11, 2024
5 min

banner

# AttributeError: Can only use .str accessor with string values

The NumPy "AttributeError: Can only use .str accessor with string values" occurs when you try to use the .str accessor on values that are not of type string.

To solve the error, use the astype() method to convert the values to strings before using the .str accessor.

can only use string accessors with string values

Here is an example of how the error occurs.

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, 180.2, 190.3, 205.4], }) df['salary'].str.replace('.', ',') # ⛔️ AttributeError: Can only use .str accessor with string values!. Did you mean: 'std'? print(df)

We accessed the salary column in the DataFrame and then tried to access the .str accessor.

As the error message suggests, the .str attribute can only be accessed with string values.

The salary column contains floating-point values which caused the error.

# Make sure that you are accessing the correct column

The first thing you should do is to ensure you are accessing the correct column.

For example, if I try to access the .str attribute on the name column, it is allowed because the values in the column are strings.

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, 180.2, 190.3, 205.4], }) # 0 Alice # 1 Tom # 2 Carl # 3 Dan # Name: name, dtype: object print(df['name'].str.replace('Bobby', 'Tom'))

accessing name attribute on str column works

The code for this article is available on GitHub

We accessed the str attribute on the values in the name column and used the DataFrame.replace method to replace the string Bobby with the string Tom.

You can also assign the result to the name column.

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, 180.2, 190.3, 205.4], }) df['name'] = df['name'].str.replace('Bobby', 'Tom') # name experience salary # 0 Alice 1 175.1 # 1 Tom 3 180.2 # 2 Carl 5 190.3 # 3 Dan 7 205.4 print(df)

The code sample updates the values in the name column with the result of calling replace().

# Convert the values in the column to strings before accessing .str

If you meant to access the .str attribute on a column that contains non-string values:

  1. Use the DataFrame.astype method to convert the values to strings.
  2. Access the .str attribute on the string values.
main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, 180.2, 190.3, 205.4], }) # 0 175,1 # 1 180,2 # 2 190,3 # 3 205,4 # Name: salary, dtype: object print(df['salary'].astype(str).str.replace('.', ','))

convert to string before accessing str

The code for this article is available on GitHub

We used the DataFrame.astype method to cast the values in the salary column to strings.

The only argument we passed to the astype() method is the dtype.

We can safely access the .str attribute after the values have been converted to strings.

You can also update the values in the column with the result of calling replace().

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, 180.2, 190.3, 205.4], }) df['salary'] = df['salary'].astype(str).str.replace('.', ',') # name experience salary # 0 Alice 1 175,1 # 1 Bobby 3 180,2 # 2 Carl 5 190,3 # 3 Dan 7 205,4 print(df)

We updated the values in the salary column with the result of calling DataFrame.replace().

We passed the following 2 arguments to the DataFrame.replace() method:

  1. to_replace - the values we want to replace.
  2. value - the replacement value.

# Using the apply() method to resolve the error

You can also resolve the error by calling the DataFrame.apply() method.

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, 180.2, 190.3, 205.4], }) df['salary'] = df['salary'].apply(str).str.replace('.', ',') # name experience salary # 0 Alice 1 175,1 # 1 Bobby 3 180,2 # 2 Carl 5 190,3 # 3 Dan 7 205,4 print(df)

using apply method to solve the error

The code for this article is available on GitHub

The DataFrame.apply() method applies a function along an axis of the DataFrame.

We passed the str class to the apply() method to convert each value in the salary column to a string.

After converting all values in the column to strings, we can safely access the .str attribute.

You can also pass a lambda function to the apply() method.

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, 180.2, 190.3, 205.4], }) df['salary'] = df['salary'].apply(lambda x: str(x).replace('.', ',')) # name experience salary # 0 Alice 1 175,1 # 1 Bobby 3 180,2 # 2 Carl 5 190,3 # 3 Dan 7 205,4 print(df)

The lambda function gets called with each floating-point number from the salary column.

We used the str() class to convert each floating-point number to a string and called the replace() method on each string.

# Only calling replace() if the value is a string

You can also solve the error by checking if the value is a string before calling replace().

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, '179,4', 190.3, '199,3'], }) def replace_values(value): if isinstance(value, str): return value.replace(',', '.') return value df['salary'] = df['salary'].apply(replace_values) # name experience salary # 0 Alice 1 175.1 # 1 Bobby 3 179.4 # 2 Carl 5 190.3 # 3 Dan 7 199.3 print(df)

only calling replace if value is string

The code for this article is available on GitHub
  1. The replace_values function gets called with each value from the salary column.
  2. The function uses the isinstance method to check if the given value is a string.
  3. If the condition is met, we use the replace() method to replace each comma with a period.
  4. Otherwise, the value is returned as is.

The same can be achieved using an inline lambda function.

main.py
import pandas as pd df = pd.DataFrame({ 'name': ['Alice', 'Bobby', 'Carl', 'Dan'], 'experience': [1, 3, 5, 7], 'salary': [175.1, '179,4', 190.3, '199,3'], }) df['salary'] = df['salary'].apply( lambda x: x.replace(',', '.') if isinstance(x, str) else x ) # name experience salary # 0 Alice 1 175.1 # 1 Bobby 3 179.4 # 2 Carl 5 190.3 # 3 Dan 7 199.3 print(df)
The code for this article is available on GitHub

The lambda function in the example does the same.

It only calls the replace() method if the supplied value is a string.

Otherwise, the value is returned as is.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.