def apply_noise(data, noise):
  """
  Applies noise to a sparse matrix.  Noise can be an integer between 0 and
  100, indicating the percentage of ones in the original input to move, or
  a float in [0, 1), indicating the same thing.
  The input matrix is modified in-place, and nothing is returned.
  This operation does not affect the sparsity of the matrix, or of any
  individual datapoint.
  """
  if noise >= 1:
    noise = noise/100.

  for i in range(data.nRows()):
    ones = data.rowNonZeros(i)[0]
    replace_indices = numpy.random.choice(ones,
        size = int(len(ones)*noise), replace = False)
    for index in replace_indices:
      data[i, index] = 0

    new_indices = numpy.random.choice(data.nCols(),
        size = int(len(ones)*noise), replace = False)

    for index in new_indices:
      while data[i, index] == 1:
        index = numpy.random.randint(0, data.nCols())
      data[i, index] = 1
Applies noise to a sparse matrix.  Noise can be an integer between 0 and
  100, indicating the percentage of ones in the original input to move, or
  a float in [0, 1), indicating the same thing.
  The input matrix is modified in-place, and nothing is returned.
  This operation does not affect the sparsity of the matrix, or of any
  individual datapoint.