Построить новый столбец с первым рядом группы с двумя столбцами - Панды - PullRequest
7 голосов
/ 13 мая 2019

Я пытаюсь создать новый столбец, который дает значение 1, если это первый раз, когда элемент столбца "тип" имеет определенное значение столбца "хх", и дает значение 0 в любой другой случай.

  • Исходный фрейм данных (df), с которым я работаю:

    idx = [np.array(['Jan-18', 'Jan-18', 'Feb-18', 'Mar-18', 'Mar-18', 'Mar-18','Apr-18', 'Apr-18', 'May-18', 'Jun-18', 'Jun-18', 'Jun-18','Jul-18', 'Aug-18', 'Aug-18', 'Sep-18', 'Sep-18', 'Oct-18','Oct-18', 'Oct-18', 'Nov-18', 'Dec-18', 'Dec-18',]),np.array(['A', 'B', 'B', 'A', 'B', 'C', 'A', 'B', 'B', 'A', 'B', 'C','A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'A', 'B', 'C'])]
    data = [{'xx': 1000}, {'xx': 1000}, {'xx': 1200}, {'xx': 800}, {'xx': 800}, {'xx': 800},{'xx': 1000}, {'xx': 1000}, {'xx': 800}, {'xx': 1200}, {'xx': 1200}, {'xx': 1200},{'xx': 1000}, {'xx': 1000}, {'xx': 1000}, {'xx': 1600}, {'xx': 1600}, {'xx': 1000}, {'xx': 800}, {'xx': 800}, {'xx': 1000}, {'xx': 1600}, {'xx': 1600}]
    df = pd.DataFrame(data, index=idx, columns=['xx'])
    df.index.names=['date','type']
    df=df.reset_index()
    df['date'] = pd.to_datetime(df['date'],format = '%b-%y')
    df=df.set_index(['date','type'])
    df['xx'] = df.xx.astype('float')
    
  • Результат, который я ищу:

                         xx   yy
    date       type
    2018-01-01 A     1000.0  1.0
               B     1000.0  1.0
    2018-02-01 B     1200.0  1.0
    2018-03-01 A      800.0  1.0
               B      800.0  1.0
               C      800.0  1.0
    2018-04-01 A     1000.0  0.0
               B     1000.0  0.0
    2018-05-01 B      800.0  0.0
    2018-06-01 A     1200.0  1.0
               B     1200.0  0.0
               C     1200.0  1.0
    2018-07-01 A     1000.0  0.0
    2018-08-01 B     1000.0  0.0
               C     1000.0  1.0
    2018-09-01 A     1600.0  1.0
               B     1600.0  1.0
    2018-10-01 C     1000.0  0.0
               A      800.0  0.0
               B      800.0  0.0
    2018-11-01 A     1000.0  0.0
    2018-12-01 B     1600.0  0.0
               C     1600.0  1.0
    
  • Я попробовал следующий код, но он не работает (выдает сообщение об ошибке):

    df['yy'] = df.assign(zz=(df.groupby(['type','xx']).first())).zz.transform(lambda x: 1)
    

Сообщение об ошибке гласит

ValueError: Неверное количество пропущенных элементов 0, размещение подразумевает 1.

Я пробовал другие методы, такие как nth (0), но он тоже не работает. Любое предложение о том, как решить эту проблему, очень приветствуется.

Ответы [ 4 ]

6 голосов
/ 14 мая 2019

Попробуйте:

df['yy'] = (df.groupby(level=1).xx
              .apply(lambda x: (~x.duplicated()).astype(int))
           )

df['yy']

выходы:

date        type
2018-01-01  A       1
            B       1
2018-02-01  B       1
2018-03-01  A       1
            B       1
            C       1
2018-04-01  A       0
            B       0
2018-05-01  B       0
2018-06-01  A       1
            B       0
            C       1
2018-07-01  A       0
2018-08-01  B       0
            C       1
2018-09-01  A       1
            B       1
2018-10-01  C       0
            A       0
            B       0
2018-11-01  A       0
2018-12-01  B       0
            C       1
Name: yy, dtype: int32
5 голосов
/ 14 мая 2019

Использование groupby + cumcount + astype:

df['yy'] = df.reset_index().groupby(['type','xx']).cumcount().eq(0).astype(int).values

Результат:

                     xx  yy
date       type            
2018-01-01 A     1000.0   1
           B     1000.0   1
2018-02-01 B     1200.0   1
2018-03-01 A      800.0   1
           B      800.0   1
           C      800.0   1
2018-04-01 A     1000.0   0
           B     1000.0   0
2018-05-01 B      800.0   0
2018-06-01 A     1200.0   1
           B     1200.0   0
           C     1200.0   1
2018-07-01 A     1000.0   0
2018-08-01 B     1000.0   0
           C     1000.0   1
2018-09-01 A     1600.0   1
           B     1600.0   1
2018-10-01 C     1000.0   0
           A      800.0   0
           B      800.0   0
2018-11-01 A     1000.0   0
2018-12-01 B     1600.0   0
           C     1600.0   1
4 голосов
/ 14 мая 2019

duplicated

  • Создание списка кортежей с type и xx
  • Оберните его в pandas.Series, потому что я хочу использовать pandas.Series.duplicated метод
  • Используйте numpy.where для выбора между 0 и 1

Примечание: Это не использует groupby и, следовательно, должно быть более эффективным.


s = pd.Series([*zip(df.index.get_level_values('type'), df.xx)])
df.assign(id=np.where(s.duplicated(), 0, 1))

                     xx  id
date       type            
2018-01-01 A     1000.0   1
           B     1000.0   1
2018-02-01 B     1200.0   1
2018-03-01 A      800.0   1
           B      800.0   1
           C      800.0   1
2018-04-01 A     1000.0   0
           B     1000.0   0
2018-05-01 B      800.0   0
2018-06-01 A     1200.0   1
           B     1200.0   0
           C     1200.0   1
2018-07-01 A     1000.0   0
2018-08-01 B     1000.0   0
           C     1000.0   1
2018-09-01 A     1600.0   1
           B     1600.0   1
2018-10-01 C     1000.0   0
           A      800.0   0
           B      800.0   0
2018-11-01 A     1000.0   0
2018-12-01 B     1600.0   0
           C     1600.0   1
1 голос
/ 14 мая 2019

IIUC

idx=df.groupby([df.index.get_level_values(1),df.xx]).head(1).index
df.loc[:,'new']=0
df.loc[idx,'new']=1
df
Out[869]: 
                     xx  new
date       type             
2018-01-01 A     1000.0    1
           B     1000.0    1
2018-02-01 B     1200.0    1
2018-03-01 A      800.0    1
           B      800.0    1
           C      800.0    1
2018-04-01 A     1000.0    0
           B     1000.0    0
2018-05-01 B      800.0    0
2018-06-01 A     1200.0    1
           B     1200.0    0
           C     1200.0    1
2018-07-01 A     1000.0    0
2018-08-01 B     1000.0    0
           C     1000.0    1
2018-09-01 A     1600.0    1
           B     1600.0    1
2018-10-01 C     1000.0    0
           A      800.0    0
           B      800.0    0
2018-11-01 A     1000.0    0
2018-12-01 B     1600.0    0
           C     1600.0    1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...