Down sampling with numpy

I have a 1D array A representing categorical data (where each entry is the number of an element of a certain category):

A = array([ 1, 8, 2, 5, 10, 32, 0, 0, 1, 0])

and I'm trying to write a sample (A, N) function to create an array B that contains N elements randomly generated from elements A (keeping categories):

>>> sample(A, 20)
array([ 1, 3, 0, 1, 4, 11, 0, 0, 0, 0])

I wrote this:

def sample(A, N):
    AA = A.astype(float).copy()
    Z = zeros(A.shape)
    for _ in xrange(N):
        drawn = random.multinomial(1, AA/AA.sum())
        Z = Z + drawn
        AA = AA - drawn
    return Z.astype(int)

This is probably pretty naive, is there a better / faster way to do this? Maybe using a quick numpy function? Edit: It was incomprehensible: it should be without replacement !!!

+4
source share
3 answers
As far as i can see

, . , , .

import random 
from collections import Counter

def sample2(A,N):
    distribution = [i for i, j in enumerate(A) for _ in xrange(j)]
    sample = Counter(random.sample(distribution, N))
    return [sample[i] for i in xrange(len(A))]


In [52]: A = np.random.randint(0, 100, 500)

In [53]: %timeit sample(A, 100) #Original
100 loops, best of 3: 2.71 ms per loop

In [54]: %timeit sample2(A, 100) #my function
1000 loops, best of 3: 914 Β΅s per loop

In [55]: %timeit sample3(A, 100) #sftd function
100 loops, best of 3: 8.33 ms per loop
+3

, 3 . numpy.random.choice, Boolean replace ( False - ). :

  • , A[n] counts n, . A=[2,0,3,1] choices=[0,0,2,2,2,3]. , , .
  • , numpy, . vals , choices, 1 B .

, ! :

def sample_2(A, N):
    # Create array of choices (indicies)
    choices = []
    for n in xrange(len(A)):
        for _ in xrange(A[n]):
            choices.append(n)
    # Randomly choose from these indicies
    vals = numpy.random.choice(choices, N, False)
    # Count up the chosen indicies
    B = numpy.zeros(len(A), dtype=int)
    for index in xrange(N):
        B[vals[index]] += 1
    return B

10000 :

Original: 3.0517 s
Method_2: 0.9968 s
+2

:

def sample(A, N):
        population = np.zeros(sum(A))
        counter = 0
        for i, x in enumerate(A):
                for j in range(x):
                        population[counter] = i
                        counter += 1

        sampling = population[np.random.randint(0, len(population), N)]
        return np.histogram(sampling, bins = np.arange(len(A)+1))[0]

, , A, . N (A) , / A A, . , , , sample(population, N) .

0

Source: https://habr.com/ru/post/1539330/


All Articles