summation over axis 0 (obs) equivalent to np.sum(A, 0)
336663
def sum_obs(A):
    
    return A.sum(0).A1 if issparse(A) else np.einsum('ij -> j', A)
1120441
def sum(a, axis=-1):
    """"""
    d = a.d
    crs = _vector.vector.to_list(a.tt if isinstance(a, _matrix.matrix) else a)
    if axis < 0:
        axis = range(a.d)
    elif isinstance(axis, int):
        axis = [axis]
    axis = list(axis)[::-1]
    for ax in axis:
        crs[ax] = _np.sum(crs[ax], axis=1)
        rleft, rright = crs[ax].shape
        if (rleft >= rright or rleft < rright and ax + 1 >= d) and ax > 0:
            crs[ax - 1] = _np.tensordot(crs[ax - 1], crs[ax], axes=(2, 0))
        elif ax + 1 < d:
            crs[ax + 1] = _np.tensordot(crs[ax], crs[ax + 1], axes=(1, 0))
        else:
            return _np.sum(crs[ax])
        crs.pop(ax)
        d -= 1
    return _vector.vector.from_list(crs)
111386
def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
                filter_type=None, **kwds):
        
        delegate = self._values

        if axis is not None:
            self._get_axis_number(axis)

        if isinstance(delegate, Categorical):
            # TODO deprecate numeric_only argument for Categorical and use
            # skipna as well, see GH25303
            return delegate._reduce(name, numeric_only=numeric_only, **kwds)
        elif isinstance(delegate, ExtensionArray):
            # dispatch to ExtensionArray interface
            return delegate._reduce(name, skipna=skipna, **kwds)
        elif is_datetime64_dtype(delegate):
            # use DatetimeIndex implementation to handle skipna correctly
            delegate = DatetimeIndex(delegate)

        # dispatch to numpy arrays
        elif isinstance(delegate, np.ndarray):
            if numeric_only:
                raise NotImplementedError('Series.{0} does not implement '
                                          'numeric_only.'.format(name))
            with np.errstate(all='ignore'):
                return op(delegate, skipna=skipna, **kwds)

        # TODO(EA) dispatch to Index
        # remove once all internals extension types are
        # moved to ExtensionArrays
        return delegate._reduce(op=op, name=name, axis=axis, skipna=skipna,
                                numeric_only=numeric_only,
                                filter_type=filter_type, **kwds)
274806
def accum(subs, vals, func=np.sum, issorted=False, with_subs=False):
    
    # sort accmap for ediff if not sorted
    if not issorted:
        sidx = lexsort(subs, axis=0)
        subs = [sub[sidx] for sub in subs]
        vals = vals[sidx]
    idx = np.where(np.diff(subs).any(axis=0))[0] + 1
    idx = np.concatenate(([0], idx, [subs[0].shape[0]]))

    # create values array
    nvals = np.zeros(len(idx) - 1)
    for i in range(len(idx) - 1):
        nvals[i] = func(vals[idx[i]:idx[i + 1]])

    # return results
    if with_subs:
        return nvals, tuple(sub[idx[:-1]] for sub in subs)
    else:
        return nvals
904438
def NS(s, o):
    
    # s,o = filter_nan(s,o)
    return 1 - np.sum((s-o)**2)/np.sum((o-np.mean(o))**2)
177309
def apb(s, o):
    
    # s,o = filter_nan(s,o)
    return 100.0*np.sum(np.abs(s-o))/np.sum(o)
445519
def mui(x, y):
    """"""
    assert len(x) == len(y)
    l = len(x)
    p_x = Counter(x)
    p_y = Counter(y)
    p_xy = Counter(zip(x, y))
    return sum(p_xy[(x, y)] * math.log((p_xy[(x, y)] * l) / float(p_x[x] * p_y[y]), 2) / l
               for x, y in p_xy)
896300
def sum(self, other):
        """"""
        return TimeSeries.merge(
            [self, other], operation=operations.ignorant_sum
        )
1271403
def sumad(array):
    
    n = ctypes.c_int(len(array))
    array = stypes.toDoubleVector(array)
    return libspice.sumad_c(array, n)
556790
def cumsum(self, axis=0, *args, **kwargs):
        
        nv.validate_cumsum(args, kwargs)

        if axis is None:
            axis = self._stat_axis_number

        return self.apply(lambda x: x.cumsum(), axis=axis)
851726
def _get_obs_array(self, k, use_raw=False, layer='X'):
        """"""
        in_raw_var_names = k in self.raw.var_names if self.raw is not None else False

        if use_raw and self.raw is None:
            raise ValueError('.raw doesn\'t exist')

        if k in self.obs.keys():
            x = self._obs[k]
        elif in_raw_var_names and use_raw and layer == 'X':
            x = self.raw[:, k].X
        elif k in self.var_names and not use_raw and (layer == 'X' or layer in self.layers.keys()):
            x = self[:, k].X if layer=='X' else self[:, k].layers[layer]
        elif use_raw and layer != 'X':
            raise ValueError('No layers in .raw')
        elif layer != 'X' and layer not in self.layers.keys():
            raise ValueError('Did not find {} in layers.keys.'
                             .format(layer))
        else:
            raise ValueError('Did not find {} in obs.keys or var_names.'
                             .format(k))
        return x
1174928
def transform_obs(self, obs):
    """"""
    empty = np.array([], dtype=np.int32).reshape((0, 7))
    out = named_array.NamedDict({  # Fill out some that are sometimes empty.
        "single_select": empty,
        "multi_select": empty,
        "build_queue": empty,
        "cargo": empty,
        "cargo_slots_available": np.array([0], dtype=np.int32),
    })

    def or_zeros(layer, size):
      if layer is not None:
        return layer.astype(np.int32, copy=False)
      else:
        return np.zeros((size.y, size.x), dtype=np.int32)

    aif = self._agent_interface_format

    if aif.feature_dimensions:
      out["feature_screen"] = named_array.NamedNumpyArray(
          np.stack(or_zeros(f.unpack(obs.observation),
                            aif.feature_dimensions.screen)
                   for f in SCREEN_FEATURES),
          names=[ScreenFeatures, None, None])
      out["feature_minimap"] = named_array.NamedNumpyArray(
          np.stack(or_zeros(f.unpack(obs.observation),
                            aif.feature_dimensions.minimap)
                   for f in MINIMAP_FEATURES),
          names=[MinimapFeatures, None, None])

    if aif.rgb_dimensions:
      out["rgb_screen"] = Feature.unpack_rgb_image(
          obs.observation.render_data.map).astype(np.int32)
      out["rgb_minimap"] = Feature.unpack_rgb_image(
          obs.observation.render_data.minimap).astype(np.int32)

    out["last_actions"] = np.array(
        [self.reverse_action(a).function for a in obs.actions],
        dtype=np.int32)

    out["action_result"] = np.array([o.result for o in obs.action_errors],
                                    dtype=np.int32)

    out["alerts"] = np.array(obs.observation.alerts, dtype=np.int32)

    out["game_loop"] = np.array([obs.observation.game_loop], dtype=np.int32)

    score_details = obs.observation.score.score_details
    out["score_cumulative"] = named_array.NamedNumpyArray([
        obs.observation.score.score,
        score_details.idle_production_time,
        score_details.idle_worker_time,
        score_details.total_value_units,
        score_details.total_value_structures,
        score_details.killed_value_units,
        score_details.killed_value_structures,
        score_details.collected_minerals,
        score_details.collected_vespene,
        score_details.collection_rate_minerals,
        score_details.collection_rate_vespene,
        score_details.spent_minerals,
        score_details.spent_vespene,
    ], names=ScoreCumulative, dtype=np.int32)

    def get_score_details(key, details, categories):
      row = getattr(details, key.name)
      return [getattr(row, category.name) for category in categories]

    out["score_by_category"] = named_array.NamedNumpyArray([
        get_score_details(key, score_details, ScoreCategories)
        for key in ScoreByCategory
    ], names=[ScoreByCategory, ScoreCategories], dtype=np.int32)

    out["score_by_vital"] = named_array.NamedNumpyArray([
        get_score_details(key, score_details, ScoreVitals)
        for key in ScoreByVital
    ], names=[ScoreByVital, ScoreVitals], dtype=np.int32)

    player = obs.observation.player_common
    out["player"] = named_array.NamedNumpyArray([
        player.player_id,
        player.minerals,
        player.vespene,
        player.food_used,
        player.food_cap,
        player.food_army,
        player.food_workers,
        player.idle_worker_count,
        player.army_count,
        player.warp_gate_count,
        player.larva_count,
    ], names=Player, dtype=np.int32)

    def unit_vec(u):
      return np.array((
          u.unit_type,
          u.player_relative,
          u.health,
          u.shields,
          u.energy,
          u.transport_slots_taken,
          int(u.build_progress * 100),  # discretize
      ), dtype=np.int32)

    ui = obs.observation.ui_data

    with sw("ui"):
      groups = np.zeros((10, 2), dtype=np.int32)
      for g in ui.groups:
        groups[g.control_group_index, :] = (g.leader_unit_type, g.count)
      out["control_groups"] = groups

      if ui.single:
        out["single_select"] = named_array.NamedNumpyArray(
            [unit_vec(ui.single.unit)], [None, UnitLayer])

      if ui.multi and ui.multi.units:
        out["multi_select"] = named_array.NamedNumpyArray(
            [unit_vec(u) for u in ui.multi.units], [None, UnitLayer])

      if ui.cargo and ui.cargo.passengers:
        out["single_select"] = named_array.NamedNumpyArray(
            [unit_vec(ui.single.unit)], [None, UnitLayer])
        out["cargo"] = named_array.NamedNumpyArray(
            [unit_vec(u) for u in ui.cargo.passengers], [None, UnitLayer])
        out["cargo_slots_available"] = np.array([ui.cargo.slots_available],
                                                dtype=np.int32)

      if ui.production and ui.production.build_queue:
        out["single_select"] = named_array.NamedNumpyArray(
            [unit_vec(ui.production.unit)], [None, UnitLayer])
        out["build_queue"] = named_array.NamedNumpyArray(
            [unit_vec(u) for u in ui.production.build_queue],
            [None, UnitLayer])

    def full_unit_vec(u, pos_transform, is_raw=False):
      screen_pos = pos_transform.fwd_pt(
          point.Point.build(u.pos))
      screen_radius = pos_transform.fwd_dist(u.radius)
      return np.array((
          # Match unit_vec order
          u.unit_type,
          u.alliance,  # Self = 1, Ally = 2, Neutral = 3, Enemy = 4
          u.health,
          u.shield,
          u.energy,
          u.cargo_space_taken,
          int(u.build_progress * 100),  # discretize

          # Resume API order
          int(u.health / u.health_max * 255) if u.health_max > 0 else 0,
          int(u.shield / u.shield_max * 255) if u.shield_max > 0 else 0,
          int(u.energy / u.energy_max * 255) if u.energy_max > 0 else 0,
          u.display_type,  # Visible = 1, Snapshot = 2, Hidden = 3
          u.owner,  # 1-15, 16 = neutral
          screen_pos.x,
          screen_pos.y,
          u.facing,
          screen_radius,
          u.cloak,  # Cloaked = 1, CloakedDetected = 2, NotCloaked = 3
          u.is_selected,
          u.is_blip,
          u.is_powered,
          u.mineral_contents,
          u.vespene_contents,

          # Not populated for enemies or neutral
          u.cargo_space_max,
          u.assigned_harvesters,
          u.ideal_harvesters,
          u.weapon_cooldown,
          len(u.orders),
          u.tag if is_raw else 0
      ), dtype=np.int32)

    raw = obs.observation.raw_data

    if aif.use_feature_units:
      with sw("feature_units"):
        # Update the camera location so we can calculate world to screen pos
        self._update_camera(point.Point.build(raw.player.camera))
        feature_units = []
        for u in raw.units:
          if u.is_on_screen and u.display_type != sc_raw.Hidden:
            feature_units.append(
                full_unit_vec(u, self._world_to_feature_screen_px))
        out["feature_units"] = named_array.NamedNumpyArray(
            feature_units, [None, FeatureUnit], dtype=np.int32)

    if aif.use_raw_units:
      with sw("raw_units"):
        raw_units = [full_unit_vec(u, self._world_to_world_tl, is_raw=True)
                     for u in raw.units]
        out["raw_units"] = named_array.NamedNumpyArray(
            raw_units, [None, FeatureUnit], dtype=np.int32)

    if aif.use_unit_counts:
      with sw("unit_counts"):
        unit_counts = collections.defaultdict(int)
        for u in raw.units:
          if u.alliance == sc_raw.Self:
            unit_counts[u.unit_type] += 1
        out["unit_counts"] = named_array.NamedNumpyArray(
            sorted(unit_counts.items()), [None, UnitCounts], dtype=np.int32)

    if aif.use_camera_position:
      camera_position = self._world_to_world_tl.fwd_pt(
          point.Point.build(raw.player.camera))
      out["camera_position"] = np.array((camera_position.x, camera_position.y),
                                        dtype=np.int32)

    out["available_actions"] = np.array(self.available_actions(obs.observation),
                                        dtype=np.int32)

    return out
1100358
def count_missing(self, axis=None):
        
        b = self.is_missing()
        return np.sum(b, axis=axis)
1000970
def _maybe_null_out(result, axis, mask, min_count=1):
    
    if hasattr(axis, '__len__'):  # if tuple or list
        raise ValueError('min_count is not available for reduction '
                         'with more than one dimensions.')

    if axis is not None and getattr(result, 'ndim', False):
        null_mask = (mask.shape[axis] - mask.sum(axis) - min_count) < 0
        if null_mask.any():
            dtype, fill_value = dtypes.maybe_promote(result.dtype)
            result = result.astype(dtype)
            result[null_mask] = fill_value

    elif getattr(result, 'dtype', None) not in dtypes.NAT_TYPES:
        null_mask = mask.size - mask.sum()
        if null_mask < min_count:
            result = np.nan

    return result
694265
def zscore(self, axis=1):
        
        if axis == 1:
            return self.map(lambda x: (x - mean(x)) / std(x))
        elif axis == 0:
            meanval = self.mean().toarray()
            stdval = self.std().toarray()
            return self.map(lambda x: (x - meanval) / stdval)
        else:
            raise Exception('Axis must be 0 or 1')
496282
def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
                filter_type=None, **kwds):
        
        return op(self.get_values(), skipna=skipna, **kwds)
1303003
def underflow(self, axis=0):
        
        if axis not in range(3):
            raise ValueError("axis must be 0, 1, or 2")
        if self.DIM == 1:
            return self.GetBinContent(0)
        elif self.DIM == 2:
            def idx(i):
                arg = [i]
                arg.insert(axis, 0)
                return arg
            return [
                self.GetBinContent(*idx(i))
                for i in self.bins_range(axis=(axis + 1) % 2, overflow=True)]
        elif self.DIM == 3:
            axes = [0, 1, 2]
            axes.remove(axis)
            axis2, axis3 = axes
            def idx(i, j):
                arg = [i, j]
                arg.insert(axis, 0)
                return arg
            return [[
                self.GetBinContent(*idx(i, j))
                for i in self.bins_range(axis=axis2, overflow=True)]
                for j in self.bins_range(axis=axis3, overflow=True)]