Объединение нескольких серий с разными индексами, суммирование по дублированным индексам - PullRequest
2 голосов
/ 16 апреля 2019

Предположим, у меня есть три серии

s1 = pd.Series(data=np.arange(5))
s2 = pd.Series(data=np.arange(5),index=np.arange(2,7))
s3 = pd.Series(data=np.arange(5),index=np.arange(5,10))

Какой самый эффективный способ объединить их в серию, которая суммирует data значения в дублированных индексах и сохраняет значения в недублированных индексах. Другими словами, для s1, s2, s3 мы ожидаем вывод:

0    0
1    1
2    2
3    4
4    6
5    3
6    5
7    2
8    3
9    4

В действительности мы могли бы иметь большое количество рядов с большим количеством записей данных, поэтому зацикливание неэффективно.

Ответы [ 2 ]

4 голосов
/ 16 апреля 2019

Давайте использовать concat и sum здесь:

pd.concat([s1, s2, s3]).sum(level=0)

0    0
1    1
2    2
3    4
4    6
5    3
6    5
7    2
8    3
9    4
dtype: int64

Конкатенация - это операция O (n) (линейная сложность), рекомендуется в 99% случаев.


Если вам нравится метод цепочек, этот для вас.

s1.append(s2).append(s3).sum(level=0)

0    0
1    1
2    2
3    4
4    6
5    3
6    5
7    2
8    3
9    4
dtype: int64

Не рекомендуется для более 3 серий.Добавление двух за раз оказывается квадратичным по сложности.

3 голосов
/ 16 апреля 2019

Вот один с инструментами NumPy -

def sum_series(L): # L is list of series
    aL = [list(l.index) for l in L]
    intL,unqL = pd.factorize(np.concatenate(aL))
    sums = np.bincount(intL,np.concatenate(L))
    return pd.Series(sums, index=unqL)

Пробный прогон -

In [158]: L = [s1,s2,s3] # list of series

In [159]: sum_series(L)
Out[159]: 
0    0.0
1    1.0
2    2.0
3    4.0
4    6.0
5    3.0
6    5.0
7    2.0
8    3.0
9    4.0
dtype: float64

С универсальными метками -

In [170]: L
Out[170]: 
[Label0    0
 Label1    1
 Label2    2
 Label3    3
 Label4    4
 dtype: int64, Label2    0
 Label3    1
 Label4    2
 Label5    3
 Label6    4
 dtype: int64, Label5    0
 Label6    1
 Label7    2
 Label8    3
 Label9    4
 dtype: int64]

In [171]: sum_series(L)
Out[171]: 
Label0    0.0
Label1    1.0
Label2    2.0
Label3    4.0
Label4    6.0
Label5    3.0
Label6    5.0
Label7    2.0
Label8    3.0
Label9    4.0
dtype: float64

Версия # 2

Используя объединение данных массива и используя интеллектуальный вывод dtype, возможно, более желательный вывод можно получить с помощью чего-то подобного -

def sum_series_v2(L): # L is list of series
    aL = [list(l.index) for l in L]
    v = [l.values for l in L]
    intL,unqL = pd.factorize(np.concatenate(aL))
    sums = np.bincount(intL,np.concatenate(v))
    dtype = np.result_type(*[l.dtype for l in L])
    return pd.Series(sums.astype(dtype), index=unqL)

Пример выполнения -

In [225]: sum_series_v2(L)
Out[225]: 
Label0    0
Label1    1
Label2    2
Label3    4
Label4    6
Label5    3
Label6    5
Label7    2
Label8    3
Label9    4
dtype: int64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...