<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def prepare_partial(self, X, initialization="median", k=25, **affinity_params):
 """Prepare a partial embedding which can be optimized. Parameters X: np.ndarray The data matrix to be added to the existing embedding. initialization: Union[np.ndarray, str] The initial point positions to be used in the embedding space. Can be a precomputed numpy array, ``median``, ``weighted`` or ``random``. In all cases, ``median`` of ``weighted`` should be preferred. k: int The number of nearest neighbors to consider when initially placing the point onto the embedding. This is different from ``perpelxity`` because perplexity affects optimization while this only affects the initial point positions. **affinity_params: dict Additional params to be passed to the ``Affinities.to_new`` method. Please see individual :class:`~openTSNE.affinity.Affinities` implementations as the parameters differ between implementations. Returns ------- PartialTSNEEmbedding An unoptimized :class:`PartialTSNEEmbedding` object, prepared for optimization. """

        P, neighbors, distances = self.affinities.to_new(
            X, return_distances=True, **affinity_params
        )

        # If initial positions are given in an array, use a copy of that
        if isinstance(initialization, np.ndarray):
            init_checks.num_samples(initialization.shape[0], X.shape[0])
            init_checks.num_dimensions(initialization.shape[1], self.shape[1])

            embedding = np.array(initialization)

        # Random initialization with isotropic normal distribution
        elif initialization == "random":
            embedding = initialization_scheme.random(X, self.shape[1], self.random_state)
        elif initialization == "weighted":
            embedding = initialization_scheme.weighted_mean(
                X, self, neighbors[:, :k], distances[:, :k]
            )
        elif initialization == "median":
            embedding = initialization_scheme.median(self, neighbors[:, :k])
        else:
            raise ValueError(f"Unrecognized initialization scheme `{initialization}`.")

        return PartialTSNEEmbedding(
            embedding,
            reference_embedding=self,
            P=P,
            **self.gradient_descent_params,
        )