2016-02-02 4 views
1

Мне нужна ваша помощь, чтобы отслеживать предыдущие наблюдения в рамке данных pandas.Отслеживание появления уникальных идентификаторов во временных рядах

Пример:

df = pd.DataFrame({'ID':[1,2,3,1,2,4,1,3,5]}, 
        index = ['2015-01-01','2015-01-01','2015-01-01', 
          '2015-01-02','2015-01-02','2015-01-02', 
          '2015-01-03','2015-01-03','2015-01-03']) 

Я хотел бы вернуться простой выход (панды dataframe или список), содержащий дату и замечания в этот день плюс любые другие уникальные наблюдения видели ранее

Желаемая Выход :

2015-01-01 [1,2,3] 
 
2015-01-02 [1,2,3,4] 
 
2015-01-03 [1,2,3,4,5]

У меня такое ощущение, что это будет очень простая операция в пандах, но я потерян. Не могли бы вы помочь и указать мне в правильном направлении?

Благодаря

ответ

1

Получение уникальных наблюдений по дате легко:

daily_observations = df.groupby(level=0).ID.apply(lambda s: s.unique()) 

>>> daily_observations 
2015-01-01 [1, 2, 3] 
2015-01-02 [1, 2, 4] 
2015-01-03 [1, 3, 5] 
Name: ID, dtype: object 

Накопительные их сложнее:

>>> pd.Series({idx: list(set().union(*[v.tolist() 
        for v in daily_observations.loc[daily_observations.index <= idx].values])) 
       for idx in daily_observations.index}) 

    2015-01-01   [1, 2, 3] 
    2015-01-02  [1, 2, 3, 4] 
    2015-01-03 [1, 2, 3, 4, 5] 
    dtype: object 

Часть кода тянет кумулятивный список списков для все вхождения.

>>> [daily_observations.loc[daily_observations.index <= idx].values for idx in daily_observations.index] 
[array([array([1, 2, 3])], dtype=object), 
array([array([1, 2, 3]), array([1, 2, 4])], dtype=object), 
array([array([1, 2, 3]), array([1, 2, 4]), array([1, 3, 5])], dtype=object)] 

, который затем преобразуется из массивов в список списков для каждого значения индекса:

>>> [[v.tolist() for v in daily_observations.loc[daily_observations.index <= idx].values] for idx in daily_observations.index] 
[[[1, 2, 3]], [[1, 2, 3], [1, 2, 4]], [[1, 2, 3], [1, 2, 4], [1, 3, 5]]] 

Эти списки списков затем преобразуются в наборы через союз, а затем преобразуется обратно в списки.

>>> [list(set().union(*[v.tolist() 
         for v in daily_observations.loc[daily_observations.index <= idx].values])) 
      for idx in daily_observations.index] 
[[1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]] 

Все вышеперечисленное затем завернуто в понимание словаря, которое затем используется для построения Серии.

2

Это может быть не самой лучшей идеей, если есть огромное количество ценностей, и я напоминаю вам, что объекты панд не предназначены для проведения нескалярных объектов, но вы можете использовать get_dummies:

>>> d = pd.get_dummies(df["ID"]) 
>>> m = d.cummax().groupby(level=0).last() 
>>> m.apply(lambda x: m.columns[x.astype(bool)].tolist(), axis=1) 
2015-01-01   [1, 2, 3] 
2015-01-02  [1, 2, 3, 4] 
2015-01-03 [1, 2, 3, 4, 5] 
dtype: object 

Это работает потому, что манекены дает нам членство таблицу:

>>> d 
      1 2 3 4 5 
2015-01-01 1 0 0 0 0 
2015-01-01 0 1 0 0 0 
2015-01-01 0 0 1 0 0 
2015-01-02 1 0 0 0 0 
2015-01-02 0 1 0 0 0 
2015-01-02 0 0 0 1 0 
2015-01-03 1 0 0 0 0 
2015-01-03 0 0 1 0 0 
2015-01-03 0 0 0 0 1 

и мы можем накапливать эти:

>>> d.cummax().groupby(level=0).last() 
      1 2 3 4 5 
2015-01-01 1 1 1 0 0 
2015-01-02 1 1 1 1 0 
2015-01-03 1 1 1 1 1 
+0

Это очень крутое решение. – Alexander