def aggregate_by(self, tagnames, array):
        """
        :param tagnames: a list of valid tag names
        :param array: an array with the same length as the asset collection
        :returns: an array of aggregate values with the proper shape
        """
        missing = set(tagnames) - set(self.tagcol.tagnames)
        if missing:
            raise ValueError('Unknown tagname(s) %s' % missing)
        A, *shp = array.shape
        if A != len(self):
            raise ValueError('The array must have length %d, got %d' %
                             (len(self), A))
        if not tagnames:
            return array.sum(axis=0)
        shape = [len(getattr(self.tagcol, tagname))-1 for tagname in tagnames]
        acc = numpy.zeros(shape, (F32, shp) if shp else F32)
        for asset, row in zip(self.array, array):
            acc[tuple(idx - 1 for idx in asset[tagnames])] += row
        return acc
:param tagnames: a list of valid tag names
        :param array: an array with the same length as the asset collection
        :returns: an array of aggregate values with the proper shape