web-dev-qa-db-fra.com

Lire le fichier et tracer CDF en Python

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()
6
Phani.lav

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

Pour être complet, vous devriez également considérer:

  • doublons: vous pourriez avoir le même point plusieurs fois dans vos données. 
  • les points peuvent avoir des distances différentes entre eux
  • les points peuvent être flottants

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:

 CDF


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

 Interpolation

4
Amedeo

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

2
vergil_chiou

En réponse rapide,

plt.plot(sorted_data, np.linspace(0,1,sorted_data.size)

j'aurais du vous donner

2
nayyarv

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)
1
Allen Downey