<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 2A.i - Mesures de vitesse sur les dataframes
Lire un dataframe avec un itérateur quand on ne connaît pas sa taille, lire un array avec un itérateur.
Step1:  Création d'un dataframe à partir d'un itérateur
On cherche à créer un dataframe à partir d'un ensemble de lignes dont on ne connaît pas le nombre au moment où on créé le dataframe car on les reçoit sous la forme d'un itérateur ou un générateur.
Step2:  On compare plusieurs constructions 
Step3:  On décompose 
Step4:  D'après ces temps, pandas convertit probablement l'itérateur en liste. On essaye de créer le dataframe vide, puis avec la méthode from_records.
Step5:  Création d'un array à partir d'un itérateur
On cherche à créer un dataframe à partir d'un ensemble de lignes dont on ne connaît pas le nombre au moment où on créé le dataframe car on les reçoit sous la forme d'un itérateur ou un générateur. La documentation de la fonction numpy.fromiter est intéressante à ce sujet.
Step6:  Et si on ne précise pas la taille du tableau créé avec la fonction fromiter 
<ASSISTANT_TASK:>
Python Code:
from jyquickhelper import add_notebook_menu
add_notebook_menu()
Explanation: 2A.i - Mesures de vitesse sur les dataframes
Lire un dataframe avec un itérateur quand on ne connaît pas sa taille, lire un array avec un itérateur.
End of explanation
import random
def enumerate_row(nb=10000, n=10):
    for i in range(nb):
        # on retourne un tuple, les données sont
        # plus souvent recopiées car le type est immuable
        yield tuple(random.random() for k in range(n))
        # on retourne une liste, ces listes ne sont pas
        # recopiées en général, seule la liste qui les tient
        # l'est
        # yield list(random.random() for k in range(n))
        
list(enumerate_row(2))
import pandas
nb, n = 10, 10
df = pandas.DataFrame(enumerate_row(nb=nb, n=n), columns=["c%d" % i for i in range(n)])
df.head()
nb, n =100000, 10
Explanation: Création d'un dataframe à partir d'un itérateur
On cherche à créer un dataframe à partir d'un ensemble de lignes dont on ne connaît pas le nombre au moment où on créé le dataframe car on les reçoit sous la forme d'un itérateur ou un générateur.
End of explanation
print(nb,n)
%timeit pandas.DataFrame(enumerate_row(nb=nb,n=n), columns=["c%d" % i for i in range(n)])
print(nb,n)
%timeit pandas.DataFrame(list(enumerate_row(nb=nb,n=n)), columns=["c%d" % i for i in range(n)])
Explanation: On compare plusieurs constructions :
End of explanation
def cache():
    return list(enumerate_row(nb=nb,n=n))
print(nb,n)
%timeit cache()
print(nb,n)
l = list(enumerate_row(nb=nb,n=n))
%timeit pandas.DataFrame(l, columns=["c%d" % i for i in range(n)])
Explanation: On décompose :
End of explanation
%timeit pandas.DataFrame(columns=["c%d" % i for i in range(n)], index=range(n))
def create_df3():
    return pandas.DataFrame.from_records(enumerate_row(nb=nb,n=n), 
                                         columns=["c%d" % i for i in range(n)])
print(nb,n)
%timeit create_df3()
Explanation: D'après ces temps, pandas convertit probablement l'itérateur en liste. On essaye de créer le dataframe vide, puis avec la méthode from_records.
End of explanation
def enumerate_row2(nb=10000, n=10):
    for i in range(nb):
        for k in range(n):
            yield random.random()
            
import numpy
nb,n = 100000, 10
# on précise la taille du tableau car cela évite à numpy d'agrandir le tableau
# au fur et à mesure, ceci ne fonctionne pas
print(nb,n)
m = numpy.fromiter(enumerate_row2(nb=nb,n=n), float, nb*n)
m.resize((nb,n))
m [:5,:]
def create_array():
    m = numpy.fromiter(enumerate_row2(nb=nb,n=n), float, nb*n)
    m.resize((nb,n))    
    return m
print(nb,n)
%timeit create_array()
def create_array2():
    m = list(enumerate_row(nb=nb,n=n))
    ml = numpy.array(m, float)
    return ml
print(nb,n)
%timeit create_array2()
Explanation: Création d'un array à partir d'un itérateur
On cherche à créer un dataframe à partir d'un ensemble de lignes dont on ne connaît pas le nombre au moment où on créé le dataframe car on les reçoit sous la forme d'un itérateur ou un générateur. La documentation de la fonction numpy.fromiter est intéressante à ce sujet.
End of explanation
def create_array3():
    m = numpy.fromiter(enumerate_row2(nb=nb,n=n), float)
    m.resize((nb,n))    
    return m
print(nb,n)
%timeit create_array3()
Explanation: Et si on ne précise pas la taille du tableau créé avec la fonction fromiter :
End of explanation
<END_TASK>