TypeError: only length-1 arrays can be converted to Python scalars while plot showing
Question:
I have such Python code:
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return np.int(x)
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f(x))
plt.show()
And such error:
TypeError: only length-1 arrays can be converted to Python scalars
How can I fix it?
Answers:
Take note of what is printed for x
. You are trying to convert an array (basically just a list) into an int. length-1
would be an array of a single number, which I assume numpy just treats as a float. You could do this, but it’s not a purely-numpy solution.
EDIT: I was involved in a post a couple of weeks back where numpy was slower an operation than I had expected and I realised I had fallen into a default mindset that numpy was always the way to go for speed. Since my answer was not as clean as ayhan’s, I thought I’d use this space to show that this is another such instance to illustrate that vectorize
is around 10% slower than building a list in Python. I don’t know enough about numpy to explain why this is the case but perhaps someone else does?
import numpy as np
import matplotlib.pyplot as plt
import datetime
time_start = datetime.datetime.now()
# My original answer
def f(x):
rebuilt_to_plot = []
for num in x:
rebuilt_to_plot.append(np.int(num))
return rebuilt_to_plot
for t in range(10000):
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f(x))
time_end = datetime.datetime.now()
# Answer by ayhan
def f_1(x):
return np.int(x)
for t in range(10000):
f2 = np.vectorize(f_1)
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f2(x))
time_end_2 = datetime.datetime.now()
print time_end - time_start
print time_end_2 - time_end
The error "only length-1 arrays can be converted to Python scalars" is raised when the function expects a single value but you pass an array instead.
np.int
was an alias for the built-in int
, which is deprecated in numpy v1.20. The argument for int should be a scalar and it does not accept array-like objects. In general, if you want to apply a function to each element of the array, you can use np.vectorize
:
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return int(x)
f2 = np.vectorize(f)
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f2(x))
plt.show()
You can skip the definition of f(x) and just pass the function int
to the vectorize function: f2 = np.vectorize(int)
.
Note that np.vectorize
is just a convenience function and basically a for loop. That will be inefficient over large arrays. Whenever you have the possibility, use truly vectorized functions or methods (like astype(int)
as @FFT suggests).
dataframe['column'].squeeze()
should solve this. It basically changes the dataframe column to a list.
In this case the output has to be a rounded int
values.
import numpy as np
arr = np.array([2.34, 2.56, 3.12])
output = np.round(arr).astype(int)
print(output)
# array([2, 3, 3])
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return np.array(list(map(np.int, x)))
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f(x))
plt.show()
using np.array(list(map(np.int, x))) will converge numpy array to scaler value and fix the issue for more detail visit this detailed article.
I have such Python code:
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return np.int(x)
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f(x))
plt.show()
And such error:
TypeError: only length-1 arrays can be converted to Python scalars
How can I fix it?
Take note of what is printed for x
. You are trying to convert an array (basically just a list) into an int. length-1
would be an array of a single number, which I assume numpy just treats as a float. You could do this, but it’s not a purely-numpy solution.
EDIT: I was involved in a post a couple of weeks back where numpy was slower an operation than I had expected and I realised I had fallen into a default mindset that numpy was always the way to go for speed. Since my answer was not as clean as ayhan’s, I thought I’d use this space to show that this is another such instance to illustrate that vectorize
is around 10% slower than building a list in Python. I don’t know enough about numpy to explain why this is the case but perhaps someone else does?
import numpy as np
import matplotlib.pyplot as plt
import datetime
time_start = datetime.datetime.now()
# My original answer
def f(x):
rebuilt_to_plot = []
for num in x:
rebuilt_to_plot.append(np.int(num))
return rebuilt_to_plot
for t in range(10000):
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f(x))
time_end = datetime.datetime.now()
# Answer by ayhan
def f_1(x):
return np.int(x)
for t in range(10000):
f2 = np.vectorize(f_1)
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f2(x))
time_end_2 = datetime.datetime.now()
print time_end - time_start
print time_end_2 - time_end
The error "only length-1 arrays can be converted to Python scalars" is raised when the function expects a single value but you pass an array instead.
np.int
was an alias for the built-in int
, which is deprecated in numpy v1.20. The argument for int should be a scalar and it does not accept array-like objects. In general, if you want to apply a function to each element of the array, you can use np.vectorize
:
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return int(x)
f2 = np.vectorize(f)
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f2(x))
plt.show()
You can skip the definition of f(x) and just pass the function int
to the vectorize function: f2 = np.vectorize(int)
.
Note that np.vectorize
is just a convenience function and basically a for loop. That will be inefficient over large arrays. Whenever you have the possibility, use truly vectorized functions or methods (like astype(int)
as @FFT suggests).
dataframe['column'].squeeze()
should solve this. It basically changes the dataframe column to a list.
In this case the output has to be a rounded int
values.
import numpy as np
arr = np.array([2.34, 2.56, 3.12])
output = np.round(arr).astype(int)
print(output)
# array([2, 3, 3])
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return np.array(list(map(np.int, x)))
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f(x))
plt.show()
using np.array(list(map(np.int, x))) will converge numpy array to scaler value and fix the issue for more detail visit this detailed article.