<commit_before>import numpy as np

import param

from ..core import util
from ..core import OrderedDict, Dimension, UniformNdMapping, Element, Element2D, NdElement, HoloMap
from .tabular import ItemTable, Table


class Chart(Element2D):
    """
    The data held within Chart is a numpy array of shape (N, D),
    where N is the number of samples and D the number of dimensions.
    Chart Elements are sliceable along up to two key dimensions.
    The data may be supplied in one of three formats:

    1) As a numpy array of shape (N, D).
    2) As a list of length N containing tuples of length D.
    3) As a tuple of length D containing iterables of length N.
    """

    kdims = param.List(default=[Dimension('x')], bounds=(1,2), doc="""
        The key dimensions of the Chart, determining the number of
        indexable dimensions.""")

    group = param.String(default='Chart', constant=True)

    vdims = param.List(default=[Dimension('y')], bounds=(1,None), doc="""
        The value dimensions of the Chart, usually corresponding to a
        number of dependent variables.""")

    _null_value = np.array([[], []]).T # For when data is None

    def __init__(self, data, **kwargs):
        data, params = self._process_data(data)
        params.update(kwargs)
        super(Chart, self).__init__(data, **params)
        self.data = self._validate_data(self.data)


    def _convert_element(self, element):
        if isinstance(element, Chart):
            return element.data
        elif isinstance(element, NdElement):
            return np.vstack([np.concatenate([key, vals])
                              for key, vals in element.data.items()]).astype(np.float)
        else:
            return super(Chart, self)._convert_element(element)


    def _process_data(self, data):
        params = {}
        if isinstance(data, UniformNdMapping) or (isinstance(data, list) and data
                                                  and isinstance(data[0], Element2D)):
            params = dict([v for v in data][0].get_param_values(onlychanged=True))
            data = np.concatenate([v.data for v in data])
        elif isinstance(data, Element):
            pass
        elif isinstance(data, tuple):
            data = np.column_stack(data)
        elif not isinstance(data, np.ndarray):
            data = list(data)
            data = self._null_value if (data is None) or (len(data) == 0) else data
            if len(data):
                data = np.array(data)

        return data, params


    def _validate_data(self, data):
        if data.ndim == 1:
            data = np.array(list(zip(range(len(data)), data)))
        if not data.shape[1] == len(self.dimensions()):
            raise ValueError("Data has to match number of key and value dimensions")
        return data


    def closest(self, coords):
        """
        Given single or multiple x-values, returns the list
        of closest actual samples.
        """
        if not isinstance(coords, list): coords = [coords]
        xs = self.data[:, 0]
        idxs = [np.argmin(np.abs(xs-coord)) for coord in coords]
        return [xs[idx] for idx in idxs]


    def __getitem__(self, slices):
        """
        Implements slicing or indexing of the data by the data x-value.
        If a single element is indexed reduces the Element2D to a single
        Scatter object.
        """
        if slices is ():
            return self
        if not isinstance(slices, tuple): slices = (slices,)
        if len(slices) > self.ndims:
            raise Exception("Slice must match number of key dimensions.")

        data = self.data
        lower_bounds, upper_bounds = [], []
        for idx, slc in enumerate(slices):
            if isinstance(slc, slice):
                start = slc.start if slc.start else -float("inf")
                stop = slc.stop if slc.stop else float("inf")

                clip_start = start <= data[:, idx]
                clip_stop = data[:, idx] < stop
                data = data[np.logical_and(clip_start, clip_stop), :]
                lbound = self.extents[idx]
                ubound = self.extents[self.ndims:][idx]
                lower_bounds.append(lbound if slc.start is None else slc.start)
                upper_bounds.append(ubound if slc.stop is None else slc.stop)
            else:
                data_index = data[:, idx] == slc
                if not any(data_index):
                    raise IndexError("Value %s not found in data." % slc)
                data = data[data_index, :]
        if not any(isinstance(slc, slice) for slc in slices):
            data = data[:, self.ndims:]
            return data[0] if data.shape[1] == 1 else data
        if self.ndims == 1:
            lower_bounds.append(None)
            upper_bounds.append(None)

        return self.clone(data, extents=tuple(lower_bounds + upper_bounds))
<commit_msg>Minor fix to Chart slicing<commit_after>import numpy as np

import param

from ..core import util
from ..core import OrderedDict, Dimension, UniformNdMapping, Element, Element2D, NdElement, HoloMap
from .tabular import ItemTable, Table


class Chart(Element2D):
    """
    The data held within Chart is a numpy array of shape (N, D),
    where N is the number of samples and D the number of dimensions.
    Chart Elements are sliceable along up to two key dimensions.
    The data may be supplied in one of three formats:

    1) As a numpy array of shape (N, D).
    2) As a list of length N containing tuples of length D.
    3) As a tuple of length D containing iterables of length N.
    """

    kdims = param.List(default=[Dimension('x')], bounds=(1,2), doc="""
        The key dimensions of the Chart, determining the number of
        indexable dimensions.""")

    group = param.String(default='Chart', constant=True)

    vdims = param.List(default=[Dimension('y')], bounds=(1,None), doc="""
        The value dimensions of the Chart, usually corresponding to a
        number of dependent variables.""")

    _null_value = np.array([[], []]).T # For when data is None

    def __init__(self, data, **kwargs):
        data, params = self._process_data(data)
        params.update(kwargs)
        super(Chart, self).__init__(data, **params)
        self.data = self._validate_data(self.data)


    def _convert_element(self, element):
        if isinstance(element, Chart):
            return element.data
        elif isinstance(element, NdElement):
            return np.vstack([np.concatenate([key, vals])
                              for key, vals in element.data.items()]).astype(np.float)
        else:
            return super(Chart, self)._convert_element(element)


    def _process_data(self, data):
        params = {}
        if isinstance(data, UniformNdMapping) or (isinstance(data, list) and data
                                                  and isinstance(data[0], Element2D)):
            params = dict([v for v in data][0].get_param_values(onlychanged=True))
            data = np.concatenate([v.data for v in data])
        elif isinstance(data, Element):
            pass
        elif isinstance(data, tuple):
            data = np.column_stack(data)
        elif not isinstance(data, np.ndarray):
            data = list(data)
            data = self._null_value if (data is None) or (len(data) == 0) else data
            if len(data):
                data = np.array(data)

        return data, params


    def _validate_data(self, data):
        if data.ndim == 1:
            data = np.array(list(zip(range(len(data)), data)))
        if not data.shape[1] == len(self.dimensions()):
            raise ValueError("Data has to match number of key and value dimensions")
        return data


    def closest(self, coords):
        """
        Given single or multiple x-values, returns the list
        of closest actual samples.
        """
        if not isinstance(coords, list): coords = [coords]
        xs = self.data[:, 0]
        idxs = [np.argmin(np.abs(xs-coord)) for coord in coords]
        return [xs[idx] for idx in idxs]


    def __getitem__(self, slices):
        """
        Implements slicing or indexing of the data by the data x-value.
        If a single element is indexed reduces the Element2D to a single
        Scatter object.
        """
        if slices is ():
            return self
        if not isinstance(slices, tuple): slices = (slices,)
        if len(slices) > self.ndims:
            raise Exception("Slice must match number of key dimensions.")

        data = self.data
        lower_bounds, upper_bounds = [], []
        for idx, slc in enumerate(slices):
            if isinstance(slc, slice):
                start = -float("inf") if slc.start is None else slc.start
                stop = float("inf") if slc.stop is None else slc.stop

                clip_start = start <= data[:, idx]
                clip_stop = data[:, idx] < stop
                data = data[np.logical_and(clip_start, clip_stop), :]
                lbound = self.extents[idx]
                ubound = self.extents[self.ndims:][idx]
                lower_bounds.append(lbound if slc.start is None else slc.start)
                upper_bounds.append(ubound if slc.stop is None else slc.stop)
            else:
                data_index = data[:, idx] == slc
                if not any(data_index):
                    raise IndexError("Value %s not found in data." % slc)
                data = data[data_index, :]
        if not any(isinstance(slc, slice) for slc in slices):
            data = data[:, self.ndims:]
            return data[0] if data.shape[1] == 1 else data
        if self.ndims == 1:
            lower_bounds.append(None)
            upper_bounds.append(None)

        return self.clone(data, extents=tuple(lower_bounds + upper_bounds))

{'fraction_non_alphanumeric': 0.10364174232377843, 'fraction_numerical': 0.004080383556054269, 'mean_word_length': 2.1113932085052363, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3713097', 'n_tokens_mistral': 2799, 'n_tokens_neox': 2712, 'n_words': 922}