J'ai besoin de lire un fichier long avec un horodatage en secondes et un tracé de CDF utilisant numpy ou scipy. J'ai essayé avec numpy mais il semble que la sortie ne soit PAS ce qu'elle est supposée être. Le code ci-dessous: Toutes les suggestions appréciées.
import numpy as np
import matplotlib.pyplot as plt
data = np.loadtxt('Filename.txt')
sorted_data = np.sort(data)
cumulative = np.cumsum(sorted_data)
plt.plot(cumulative)
plt.show()
Vous avez deux options:
1: vous pouvez d'abord stocker les données. Cela peut être fait facilement avec la fonction numpy.histogram
:
import numpy en tant que np import matplotlib.pyplot en tant que plt data = np.loadtxt ('Filename.txt') # Choisissez le nombre de bacs que vous voulez ici Num_bins = 20 # Utilisez la fonction d'histogramme pour classer les données , Bin_edges = np.histogram ( data, bins = num_bins, normed = True) # Recherchez maintenant le fichier cdf cdf = np.cumsum (points) # Et enfin, tracez le cdf Plt.plot (bin_edges [1:], cdf) plt.show ()
2: plutôt que d'utiliser numpy.cumsum
, tracez simplement le tableau sorted_data
par rapport au nombre d'éléments plus petits que chaque élément du tableau (voir cette réponse pour plus de détails https://stackoverflow.com/a/11692365/588071 ):
import numpy en tant que np import matplotlib.pyplot en tant que plt data = np.loadtxt ('Filename.txt') ordres_sélectionnés = np.sort (données) yvals = np.arange (len (données_séparées))/float (len (données_organisées) -1) plt.plot (trier les données, yvals) plt.show ()
Pour être complet, vous devriez également considérer:
Vous pouvez utiliser numpy.histogram
pour définir les bords des bacs de manière à ce que chaque bac ne collecte toutes les occurrences d’un point. Vous devriez garder density=False
car, selon la documentation:
Notez que la somme des valeurs de l'histogramme ne sera pas égale à 1 à moins que des segments de largeur unitaire ne soient choisis
Vous pouvez normaliser à la place le nombre d'éléments dans chaque bac en le divisant par la taille de vos données.
import numpy as np
import matplotlib.pyplot as plt
def cdf(data):
data_size=len(data)
# Set bins edges
data_set=sorted(set(data))
bins=np.append(data_set, data_set[-1]+1)
# Use the histogram function to bin the data
counts, bin_edges = np.histogram(data, bins=bins, density=False)
counts=counts.astype(float)/data_size
# Find the cdf
cdf = np.cumsum(counts)
# Plot the cdf
plt.plot(bin_edges[0:-1], cdf,linestyle='--', marker="o", color='b')
plt.ylim((0,1))
plt.ylabel("CDF")
plt.grid(True)
plt.show()
Par exemple, avec les données suivantes:
#[ 0. 0. 0.1 0.1 0.2 0.2 0.3 0.3 0.4 0.4 0.6 0.8 1. 1.2]
data = np.concatenate((np.arange(0,0.5,0.1),np.arange(0.6,1.4,0.2),np.arange(0,0.5,0.1)))
cdf(data)
vous auriez:
Vous pouvez également interpoler le fichier cdf pour obtenir une fonction continue (avec une interpolation linéaire ou une spline cubique):
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
def cdf(data):
data_size=len(data)
# Set bins edges
data_set=sorted(set(data))
bins=np.append(data_set, data_set[-1]+1)
# Use the histogram function to bin the data
counts, bin_edges = np.histogram(data, bins=bins, density=False)
counts=counts.astype(float)/data_size
# Find the cdf
cdf = np.cumsum(counts)
x = bin_edges[0:-1]
y = cdf
f = interp1d(x, y)
f2 = interp1d(x, y, kind='cubic')
xnew = np.linspace(0, max(x), num=1000, endpoint=True)
# Plot the cdf
plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')
plt.legend(['data', 'linear', 'cubic'], loc='best')
plt.title("Interpolation")
plt.ylim((0,1))
plt.ylabel("CDF")
plt.grid(True)
plt.show()
Voici l'étape de ma mise en œuvre:
1.sort vos données
2.calculer la probabilité cumulée de chaque 'x'
import numpy as np
import matplotlib.pyplab as plt
def cdf(data):
n = len(data)
x = np.sort(data) # sort your data
y = np.arange(1, n + 1) / n # calculate cumulative probability
return x, y
x_data, y_data = cdf(your_data)
plt.plot(x_data, y_data)
Exemple:
test_data = np.random.normal(size= 100)
x_data, y_data = ecdf(test_data)
plt.plot(x_data, y_data, marker= '.', linestyle= 'none')
Figure: Le lien du graphe
En réponse rapide,
plt.plot(sorted_data, np.linspace(0,1,sorted_data.size)
j'aurais du vous donner
Voici une implémentation un peu plus efficace s'il y a beaucoup de valeurs répétées (puisqu'il suffit de trier les valeurs uniques). Et il trace le CDF comme une fonction étape, ce qu’il est, à proprement parler.
import sys
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter
def read_data(fp):
t = []
for line in fp:
x = float(line.rstrip())
t.append(x)
return t
def main(script, filename=None):
if filename is None:
fp = sys.stdin
else:
fp = open(filename)
t = read_data(fp)
counter = Counter(t)
xs = counter.keys()
xs.sort()
ys = np.cumsum(counter.values()).astype(float)
ys /= ys[-1]
options = dict(linewidth=3, alpha=0.5)
plt.step(xs, ys, where='post', **options)
plt.xlabel('Values')
plt.ylabel('CDF')
plt.show()
if __== '__main__':
main(*sys.argv)