web-dev-qa-db-fra.com

TypeError: seuls les tableaux de longueur 1 peuvent être convertis en scalaires Python pendant l'affichage du tracé.

J'ai un tel code Python:

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()

Et telle erreur:

TypeError: only length-1 arrays can be converted to Python scalars

Comment puis-je le réparer?

14
K. Kovalev

L'erreur "seuls les tableaux de longueur 1 peuvent être convertis en scalaires Python" est générée lorsque la fonction s'attend à une valeur unique mais que vous transmettez plutôt un tableau. 

Si vous regardez la signature d'appel de np.int, vous verrez qu'elle accepte une valeur unique, pas un tableau. En général, si vous souhaitez appliquer une fonction qui accepte un seul élément à chaque élément d'un tableau, vous pouvez utiliser np.vectorize :

import numpy as np
import matplotlib.pyplot as plt

def f(x):
    return np.int(x)
f2 = np.vectorize(f)
x = np.arange(1, 15.1, 0.1)
plt.plot(x, f2(x))
plt.show()

Vous pouvez ignorer la définition de f(x) et simplement transmettre np.int à la fonction de vectorisation: f2 = np.vectorize(np.int).

Notez que np.vectorize est simplement une fonction pratique et une boucle for. Ce sera inefficace sur les grands tableaux. Chaque fois que vous en avez la possibilité, utilisez des fonctions ou des méthodes réellement vectorisées (comme astype(int) comme @FFT le suggère ). 

17
ayhan

Utilisation: 

x.astype(int)

Voici le reference .

5
FFT

Prenez note de ce qui est imprimé pour x. Vous essayez de convertir un tableau (simplement une liste) en un entier. length-1 serait un tableau composé d'un nombre unique, ce qui, je suppose, est considéré par numpy comme un float. Vous pouvez le faire, mais ce n'est pas une solution purement numérique.

EDIT: J'ai été impliqué dans un message il y a quelques semaines, dans lequel Numpy était une opération plus lente que prévu et je me suis rendu compte que j'étais tombé dans un état d'esprit par défaut voulant que Numpy soit toujours le meilleur moyen d'aller vite. Comme ma réponse n'était pas aussi nette que celle d'ayhan, j'ai pensé utiliser cet espace pour montrer qu'il s'agit d'un autre exemple illustrant le fait que vectorize est environ 10% plus lent que la construction d'une liste en Python. Je ne sais pas assez sur numpy pour expliquer pourquoi c'est le cas mais peut-être quelqu'un d'autre le sait-il? 

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
1
roganjosh