def nb_cluster(data, k, P_init=None, R_init=None, assignments=None, means=None, max_iters=<NUM_LIT:10>):
genes, cells = data.shape<EOL>if P_init is None:<EOL><INDENT>P_init = np.random.random((genes, k))<EOL><DEDENT>if R_init is None:<EOL><INDENT>R_init = np.random.randint(<NUM_LIT:1>, data.max(), (genes, k))<EOL>R_init = R_init.astype(float)<EOL><DEDENT>if assignments is None:<EOL><INDENT>_, assignments = kmeans_pp(data, k, means)<EOL><DEDENT>means = np.zeros((genes, k))<EOL>old_assignments = np.copy(assignments)<EOL>for i in range(max_iters):<EOL><INDENT>nb_gene_indices = fit_cluster(data, assignments, k, P_init, R_init, means)<EOL>lls = nb_ll(data[nb_gene_indices, :], P_init[nb_gene_indices,:], R_init[nb_gene_indices,:])<EOL>lls += pois_ll.poisson_ll(data[~nb_gene_indices,:], means[~nb_gene_indices,:])<EOL>P_init[~nb_gene_indices,:] = <NUM_LIT:0><EOL>R_init[~nb_gene_indices,:] = np.inf<EOL>for c in range(cells):<EOL><INDENT>assignments[c] = np.argmax(lls[c,:])<EOL><DEDENT>if np.equal(assignments,old_assignments).all():<EOL><INDENT>break<EOL><DEDENT>old_assignments = np.copy(assignments)<EOL><DEDENT>return assignments, P_init, R_init<EOL>
Performs negative binomial clustering on the given data. If some genes have mean > variance, then these genes are fitted to a Poisson distribution.

Args:
    data (array): genes x cells
    k (int): number of clusters
    P_init (array): NB success prob param - genes x k. Default: random
    R_init (array): NB stopping param - genes x k. Default: random
    assignments (array): cells x 1 array of integers 0...k-1. Default: kmeans-pp (poisson)
    means (array): initial cluster means (for use with kmeans-pp to create initial assignments). Default: None
    max_iters (int): default: 100

Returns:
    assignments (array): 1d array of length cells, containing integers 0...k-1
    P (array): genes x k - value is 0 for genes with mean > var
    R (array): genes x k - value is inf for genes with mean > var