Je convertis une ligne multiple de chaîne en un tableau numpy, comme ceci:
names = """
1 2 1
1 1 0
0 1 1
"""
names_list = names.splitlines()
tem = []
for i in [row for row in names_list if row]:
tem.append([col for col in list(i) if col != ' '])
np.array(tem, dtype=np.int)
Ce morceau de code fonctionne cependant, j'aimerais savoir s'il existe un moyen plus efficace de faire ça?
3 Réponses :
Vous pouvez utiliser np.genfromtxt
[[1 2 1] [1 1 0] [0 1 1]]
Sortie: strong>
import numpy as np
from io import BytesIO
names = """
1 2 1
1 1 0
0 1 1
"""
print(np.genfromtxt(BytesIO(names), dtype=np.int)) #Python3 use BytesIO(names.encode('utf-8'))
Vous pouvez utiliser np.genfromtxt comme suit pour Python 3
[[1 2 1] [1 1 0] [0 1 1]]
Vous obtiendrez la sortie comme
import numpy as np
from io import BytesIO
names = """
1 2 1
1 1 0
0 1 1
"""
print(np.genfromtxt(BytesIO(names.encode('utf-8')), dtype=np.int))
#print(np.genfromtxt(BytesIO(names), dtype=np.int)) for Python 2
Une réponse a été signalée comme étant de mauvaise qualité pour ne pas s'expliquer. Mais aucun des trois autres ne le fait, et ce ne sont que des répliques l'une de l'autre.
In [251]: 'abc de f'.split()
Out[251]: ['abc', 'de', 'f']
In [252]: [i for i in list('abc de f') if i!=' ']
Out[252]: ['a', 'b', 'c', 'd', 'e', 'f']
En fait, nous n'avons pas besoin de la couche StringIO ; il suffit de diviser la chaîne en lignes (parfois nous avons besoin d'un paramètre format = None ):
def czisws(names):
names_list = names.splitlines()
tem = []
for i in [row for row in names_list if row]:
tem.append(i.split())
return np.array(tem, dtype=np.int)
In [247]: timeit czisws(names)
8.58 µs ± 274 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
La fonction d'origine est 10 fois plus rapide que celle acceptée ( s):
def orig(names):
names_list = names.splitlines()
tem = []
for i in [row for row in names_list if row]:
tem.append([col for col in list(i) if col != ' '])
return np.array(tem, dtype=np.int)
In [244]: orig(names)
Out[244]:
array([[1, 2, 1],
[1, 1, 0],
[0, 1, 1]])
In [245]: timeit orig(names)
11.1 µs ± 194 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
genfromtxt fait fondamentalement la même chose: diviser les lignes, collecter des valeurs dans une liste de listes et transformer cela en un tableau. Elle n'est pas compilée.
La réponse balisée remplace la compréhension de la liste par une méthode split :
In [242]: np.genfromtxt(names.splitlines(), dtype=int)
Out[242]:
array([[1, 2, 1],
[1, 1, 0],
[0, 1, 1]])
C'est plus rapide, ce qui n'est pas surprenant. split est une méthode de chaîne. Les méthodes intégrées sont généralement plus rapides, et préférables même si elles ne le sont pas.
Le fractionnement est également plus général:
In [227]: names = """
...: 1 2 1
...: 1 1 0
...: 0 1 1
...: """
In [238]: np.genfromtxt(StringIO(names), dtype=int)
Out[238]:
array([[1, 2, 1],
[1, 1, 0],
[0, 1, 1]])
In [239]: timeit np.genfromtxt(StringIO(names), dtype=int)
135 µs ± 286 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
si toutes les entrées sont séparées par un espace, vous pouvez appeler
i.split ("")sur les chaînes.