В пандах есть способ вычислить подраздел расширяющегося окна;без вычисления всего массива и «хвоста» результата - PullRequest
0 голосов
/ 08 июня 2018

Я хочу вычислить расширяющееся окно только нескольких последних элементов в группе ...

df = pd.DataFrame({'B': [np.nan, np.nan, 1, 1, 2, 2, 1,1], 'A': [1, 2, 1, 2, 1, 2,1,2]})

df.groupby("A")["B"].expanding().quantile(0.5)

это дает:

 1  0    NaN    
    2    1.0    
    4    1.5    
    6    1.0    
 2  1    NaN
    3    1.0
    5    1.5
    7    1.0

Я только очень хочупоследние две строки для каждой группы. результат должен быть:

 1  4    1.5    
    6    1.0    
 2  5    1.5
    7    1.0

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

РЕДАКТИРОВАТЬ: я изменил название;Многие люди правильно отвечают на часть вопроса, но игнорируют то, что является IMO важной частью (я должен был быть более ясным). Проблема в том, сколько времени нужно.Я мог бы просто «хвост» ответ, чтобы получить последние два;но затем он включает в себя вычисление первых двух «расширяющихся окон», а затем отбрасывает эти результаты.Если вместо этого мой фрейм данных имел длину 1000 строк, а мне просто нужно было ответить на несколько последних записей, большая часть этих вычислений была бы напрасной тратой времени.Это главная проблема, которая у меня есть.Как я уже сказал: «Я могу легко все это вычислить, а затем просто получить нужные разделы» => с помощью tail.Извините за путаницу.Также потенциальное использование tail не предполагает вычисление лота, но все равно кажется, что это происходит из-за времени, которое я сделал ... возможно, это не правильно, это предположение, которое я сделал.

EDIT2: другой вариант, который я пробовал, использовал min_windows при переходе, чтобы заставить его не вычислять начальные разделы группы, но это имеет много ловушек, таких как: -если массив содержит NaN, это не работает, -ifgroupbys не имеют одинаковую длину.

EDIT3: как более простая проблема и обоснование: я думаю, это ограничение расширяющегося / или скользящего окна ... скажем, у нас был массив [1,2,3,4,5] расширяющимися окнами являются [1], [1,2], [1,2,3], [1,2,3,4], [1,2,3,4,5], и еслимы запускаем максимальное значение, которое получаем: 1,2,3,4,5 (максимум каждого массива).Но если я просто хочу максимум двух последних расширяющихся окон.Мне просто нужно max [1,2,3,4] = 4 и max [1,2,3,4,5].Интуитивно понятно, что для получения двух последних результатов мне не нужно вычислять максимум из первых трех результатов расширяющегося окна.Но реализация Pandas может заключаться в том, что она вычисляет max [1,2,3,4] как max [max [1,2,3], max [4]] = 4, и в этом случае необходим расчет всего окна.Это может быть то же самое для квантильного примера.Однако может быть альтернативный способ сделать это без использования расширения ... не уверен ... это то, что я не могу решить.

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Возможно, попробуйте использовать хвост: https://pandas.pydata.org/pandas-docs/version/0.21/generated/pandas.core.groupby.GroupBy.tail.html

df.groupby('A')['B'].rolling(4, min_periods=1).quantile(0.5).reset_index(level=0).groupby('A').tail(2)
Out[410]:
   A    B
4  1  1.5
6  1  1.0
5  2  1.5
7  2  1.0

Свертывание и расширение похожи

Как насчет этого (отредактировано 12/12/2018):

def last_two_quantile(row, q):
    return pd.Series([row.iloc[:-1].quantile(q), row.quantile(q)])

df.groupby('A')['B'].apply(last_two_quantile, 0.5)
Out[126]:
A
1  0    1.5
   1    1.0
2  0    1.5
   1    1.0
Name: B, dtype: float64

Если это (или что-то подобное) не делает то, что вы хотите, я думаю, вы должны привести реальный пример вашего варианта использования.

0 голосов
/ 08 июня 2018

Вы этого хотите?

df[-4:].groupby("A")["B"].expanding().quantile(0.5)

A   
1  4    2.0
   6    1.5
2  5    2.0
   7    1.5
Name: B, dtype: float64

Надежда может помочь вам.

Solution1:

newdf = df.groupby("A")["B"].expanding().quantile(0.5).reset_index()
for i in range(newdf["A"].max()+1):
    print(newdf[newdf["A"]==i][-2:],'\n')

Solution2:

newdf2 = df.groupby("A")["B"].expanding().quantile(0.5)
for i in range(newdf2.index.get_level_values("A").max()+1):
    print(newdf[newdf["A"]==i][-2:],'\n')

Solution3:

for i in range(df.groupby("A")["B"].expanding().quantile(0.5).index.get_level_values("A").max()+1):
    print(newdf[newdf["A"]==i][-2:],'\n')

вывод:

Empty DataFrame
Columns: [A, level_1, B]
Index: [] 

   A  level_1    B
2  1        4  1.5
3  1        6  1.0 

   A  level_1    B
6  2        5  1.5
7  2        7  1.0 

новое решение:

newdf = pd.DataFrame(columns={"A", "B"})
for i in range(len(df["A"].unique())):
    newdf = newdf.append(pd.DataFrame(df[df["A"]==i+1][:-2].sum()).T)
newdf["A"] = newdf["A"]/2
for i in range(len(df["A"].unique())):
    newdf = newdf.append(df[df["A"]==df["A"].unique()[i]][-2:])
#newdf = newdf.reset_index(drop=True)
newdf["A"] = newdf["A"].astype(int)
for i in range(newdf["A"].max()+1):
    print(newdf[newdf["A"]==i].groupby("A")["B"].expanding().quantile(0.5)[-2:])

вывод:

Series([], Name: B, dtype: float64)
A   
1  4    1.5
   6    1.0
Name: B, dtype: float64
A   
2  5    1.5
   7    1.0
Name: B, dtype: float64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...