2016-05-16 4 views
1

Problem:meldet Zwei Probe K-S-Statistik aus zwei vorberechneten Histogrammen

Hier plotten I 2 Datensätze in Textdateien gespeichert (in der Liste dataset), die jeweils 21,8 Milliarden Datenpunkte. Dies macht die Daten zu groß, um sie als Array im Speicher zu halten. Ich bin immer noch in der Lage, sie als Histogramme darzustellen, aber ich bin mir nicht sicher, wie ich ihre Differenz über eine 2 sample KS test berechnen kann. Dies liegt daran, dass ich nicht herausfinden kann, wie auf jedes Histogramm im PLT-Objekt zugegriffen wird.

Beispiel:

Hier ist ein Code Dummy-Daten zu erzeugen:

mu = [100, 120] 
sigma = 30 
dataset = ['gsl_test_1.txt', 'gsl_test_2.txt'] 
for idx, file in enumerate(dataset): 
    dist = np.random.normal(mu[idx], sigma, 10000) 
    with open(file, 'w') as g: 
     for s in dist: 
      g.write('{}\t{}\t{}\n'.format('stuff', 'stuff', str(s))) 

Diese meinen beiden Histogramme erzeugt (ermöglicht here):

chunksize = 1000 
dataset = ['gsl_test_1.txt', 'gsl_test_2.txt'] 
for fh in dataset: 
    # find the min, max, line qty, for bins 
    low = np.inf 
    high = -np.inf 

    loop = 0 
    for chunk in pd.read_table(fh, header=None, chunksize=chunksize, delimiter='\t'): 
     low = np.minimum(chunk.iloc[:, 2].min(), low) 
     high = np.maximum(chunk.iloc[:, 2].max(), high) 
     loop += 1 
    lines = loop*chunksize 

    nbins = math.ceil(math.sqrt(lines)) 

    bin_edges = np.linspace(low, high, nbins + 1) 
    total = np.zeros(nbins, np.int64) # np.ndarray filled with np.uint32 zeros, CHANGED TO int64 

    for chunk in pd.read_table(fh, header=None, chunksize=chunksize, delimiter='\t'): 

     # compute bin counts over the 3rd column 
     subtotal, e = np.histogram(chunk.iloc[:, 2], bins=bin_edges) # np.ndarray filled with np.int64 

     # accumulate bin counts over chunks 
     total += subtotal 


    plt.hist(bin_edges[:-1], bins=bin_edges, weights=total) 
    plt.savefig('gsl_test_hist.svg') 

Frage:

Die meisten examples for KS-statistics verwenden zwei Arrays von Rohdaten/Beobachtungen/Punkte/etc, aber ich habe nicht genug Speicher, um diesen Ansatz zu verwenden. Per Beispiel oben, wie kann ich diese vorberechneten Bins zugreifen (von 'gsl_test_1.txt' und 'gsl_test_2.txt' die KS-Statistik zwischen den beiden Verteilungen berechnen

Bonus Karma:? Bilanz der KS-Statistik und p-Wert auf dem Graphen

Antwort

1

Ich bereinigte Ihren Code Schreiben auf StringIO b/c es ist effizienter als das Schreiben in eine Datei.Setzen Sie die Standard-Vibe w/seaborn b/c matplotlib Standardwerte sind haggard. youre bins Schwellen sollten für beide Proben identisch sein, wenn Sie möchten der stat-test, um sich anzustellen, ich denke nicht, dass du durch iterieren solltest und die Kästen auf diese Weise die ganze Sache machen wird länger dauern als es nötig ist. Sie sollten wirklich versuchen, dass Counter Sache, so dass Sie nur einmal durchschleifen müssen ... plus Sie werden in der Lage sein, die gleiche bin-Größe zu machen. Konvertieren Sie einfach Floats in Ints, da Sie sie sowieso zusammen gruppieren. from collections import Counter dann C = Counter() und C[value] += 1. Sie werden eine dict am Ende haben, wo Sie die Bins aus der list(C.keys()) machen können. Das wäre gut, weil Ihre Daten so knorrig sind. Außerdem sollten Sie sehen, ob es eine Möglichkeit gibt chunksize mit numpy anstelle von pandas b/c numpy ist schneller bei der Indexierung zu tun. versuchen Sie eine %timeit für DF.iloc[i,j] und ARRAY[i,j] und Sie werden sehen, was ich meine. i machte alles in Funktionen, so dass es mehr modular ist

import numpy as np 
import pandas as pd 
import math 
import matplotlib.pyplot as plt 
from io import StringIO 
from scipy.stats import ks_2samp 
import seaborn as sns; sns.set() 

%matplotlib inline 

#Added seaborn b/c it looks mo betta 

mu = [100, 120] 
sigma = 30 

def write_random(file,mu,sigma=30): 
    dist = np.random.normal(mu, sigma, 10000) 
    for i,s in enumerate(dist): 
     file.write('{}\t{}\t{}\n'.format("label_A-%d" % i, "label_B-%d" % i, str(s))) 
    return(file) 

#Writing to StringIO instead of an actual file 
gs1_test_1 = write_random(StringIO(),mu=100) 
gs1_test_2 = write_random(StringIO(),mu=120) 

chunksize = 1000 

def make_hist(fh,ax): 
    # find the min, max, line qty, for bins 
    low = np.inf 
    high = -np.inf 

    loop = 0 

    fh.seek(0) 
    for chunk in pd.read_table(fh, header=None, chunksize=chunksize, sep='\t'): 
     low = np.minimum(chunk.iloc[:, 2].min(), low) #btw, iloc is way slower than numpy array indexing 
     high = np.maximum(chunk.iloc[:, 2].max(), high) #you might wanna import and do the chunks with numpy 
     loop += 1 
    lines = loop*chunksize 

    nbins = math.ceil(math.sqrt(lines)) 

    bin_edges = np.linspace(low, high, nbins + 1) 
    total = np.zeros(nbins, np.int64) # np.ndarray filled with np.uint32 zeros, CHANGED TO int64 

    fh.seek(0) 
    for chunk in pd.read_table(fh, header=None, chunksize=chunksize, delimiter='\t'): 

     # compute bin counts over the 3rd column 
     subtotal, e = np.histogram(chunk.iloc[:, 2], bins=bin_edges) # np.ndarray filled with np.int64 

     # accumulate bin counts over chunks 
     total += subtotal 

    plt.hist(bin_edges[:-1], bins=bin_edges, weights=total,axes=ax,alpha=0.5) 

    return(ax,bin_edges,total) 

#Make the plot canvas to write on to give it to the function 
fig,ax = plt.subplots() 

test_1_data = make_hist(gs1_test_1,ax) 
test_2_data = make_hist(gs1_test_2,ax) 

#test_1_data[1] == test_2_data[1] The bins should be the same if you're going try and compare them... 
ax.set_title("ks: %f, p_in_the_v: %f" % ks_2samp(test_1_data[2], test_2_data[2])) 

enter image description here

Verwandte Themen