Pandas катящееся приложение ничего не делает

У меня есть DataFrame, как это:

df2 = pd.DataFrame({'date': ['2015-01-01', '2015-01-02', '2015-01-03'],
                    'value': ['a', 'b', 'a']})

         date value
0  2015-01-01     a
1  2015-01-02     b
2  2015-01-03     a

Я пытаюсь понять, как применить к нему пользовательскую функцию кадрирования. Я пробовал сделать это:

df2.rolling(2).apply(lambda x: 1)

Но это возвращает мне исходный DataFrame:

         date value
0  2015-01-01     a
1  2015-01-02     b
2  2015-01-03     a

Если у меня есть другой DataFrame, вот так:

df3 = pd.DataFrame({'a': [1, 2, 3], 'value': [4, 5, 6]})

То же самое применимо к качению:

df3.rolling(2).apply(lambda x: 1)

     a  value
0  NaN    NaN
1  1.0    1.0
2  1.0    1.0

Почему это не работает для первого DataFrame?

Pandas версия: 0.20.2

Версия для Python: 2.7.10

Обновление

Итак, я понял, что столбцы df2 являются объектными типами, тогда как выход моей лямбда-функции является целым числом. Столбцы df3 представляют собой целые столбцы. Я предполагаю, что поэтому apply не работает.

Следующая не работает:

df2.rolling(2).apply(lambda x: 'a')
         date value
0  2015-01-01     a
1  2015-01-02     b
2  2015-01-03     a

Кроме того, скажем, я хочу конкатенировать символы в столбце value на основе календаря, так что вывод функции лямбда-это строка, а не целое число. Не работает также следующее:

df2.rolling(2).apply(lambda x: '.'.join(x))

         date value
0  2015-01-01     a
1  2015-01-02     b
2  2015-01-03     a

Что здесь происходит? Могут ли операции качения применяться к столбцам типа объекта в pandas?

Ответ 1

Вот один из способов, с которым можно было бы приблизиться. Отмечая, что rolling является оберткой для методов numpy и эффективностью, связанной с ними, это не так. Это просто обеспечивает аналогичную api, чтобы разрешить перекатывание нечисловых столбцов:

Код:

import pandas as pd

class MyDataFrame(pd.DataFrame):

    @property
    def _constructor(self):
        return MyDataFrame

    def rolling_object(self, window, column, default):
        return pd.concat(
            [self[column].shift(i) for i in range(window)],
            axis=1).fillna(default).T

Это создает собственный класс dataframe, который имеет метод rolling_object. Он не соответствует формату pandas тем, что он работает только с одним столбцом за раз.

Код проверки:

df2 = MyDataFrame({'date': ['2015-01-01', '2015-01-02', '2015-01-03'],
                   'value': ['a', 'b', 'c'],
                   'num': [1, 2, 3]
                   })

print(df2.rolling_object(2, 'value', '').apply(lambda x: '.'.join(x)))

Результаты:

0     a.
1    b.a
2    c.b
dtype: object