Проверьте уникальность серий в объектах Pandas Groupby - PullRequest
0 голосов
/ 05 февраля 2019

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

Примите во внимание следующее:

df = pd.DataFrame({'key': [1, 1, 2, 2, 3, 3, 2, 4], 'type': ['correct', 'incorrect', 'missed', 'incorrect', 'missed', 'missed', 'correct', 'pass']})
df

  key   type
0   1   correct
1   1   incorrect
2   2   missed
3   2   incorrect
4   3   missed
5   3   missed
6   2   correct
7   4   pass

Я пытаюсь получить исходный кадр данных для просмотракак это.Где only_missed равно yes, если missed является единственным типом в группе.

    key type    only_missed
0   1   correct     no
1   1   incorrect   no
2   2   missed      no
3   2   incorrect   no
4   3   missed      yes
5   3   missed      yes
6   2   correct     no
7   4   pass        pass

Я пробовал это, но вывод неожиданный:

a = ['correct', 'incorrect']
m = ['missed']
df['only_missed'] = df.groupby('key')['type'].transform(lambda x: 'no' if all(x.isin(a)) else ('yes' if all(x.isin(m)) else 'pass'))
df
   key  type    only_missed
0   1   correct     no
1   1   incorrect   no
2   2   missed      pass
3   2   incorrect   pass
4   3   missed      yes
5   3   missed      yes
6   2   correct     pass
7   4   pass        pass

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

Помощь очень ценится.

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019
df.groupby('key')['type'].transform(
    lambda x: 'yes'
              if (x == 'missed').all() else 
              ('pass' if (x == 'pass').all() else 'no')
)                                        
0 голосов
/ 05 февраля 2019

Одним из способов является использование логических значений и добавление их для создания категориальной категории:

In [11]: a = pd.Series(df.type.str.match('correct|incorrect').values, df.key).groupby(level=0).transform('all')

In [12]: m = pd.Series((df.type == 'missed').values, df.key).groupby(level=0).transform('all')

In [13]: pd.Categorical.from_codes(a + 2 * m, ['pass', 'no', 'yes'])
Out[13]:
[no, no, pass, pass, yes, yes, pass, pass]
Categories (3, object): [pass, no, yes]

In [14]: df["only_missed"] = pd.Categorical.from_codes(a + 2 * m, ['pass', 'no', 'yes'])

In [15]: df
Out[15]:
   key       type only_missed
0    1    correct          no
1    1  incorrect          no
2    2     missed        pass
3    2  incorrect        pass
4    3     missed         yes
5    3     missed         yes
6    2    correct        pass
7    4       pass        pass

Это выглядит как маленький хакер с .values (чтобы избежать повторной индексации)но должно быть весьма эффективным ...


Посмотрев еще раз, это был "неправильный" вывод, но я оставлю его там, поскольку он по сути тот же.Для того, чтобы получить правильное значение, вы должны посмотреть на все «пасы»:

In [21]: p = pd.Series((df.type == 'pass').values, df.key).groupby(level=0).transform('all')

In [22]: pd.Categorical.from_codes(m + 2 * p, ['no', 'yes', 'pass'])
Out[22]:
[no, no, no, no, yes, yes, no, pass]
Categories (3, object): [no, yes, pass]

In [23]: df['only_missed'] = pd.Categorical.from_codes(m + 2 * p, ['no', 'yes', 'pass'])

In [24]: df
Out[24]:
   key       type only_missed
0    1    correct          no
1    1  incorrect          no
2    2     missed          no
3    2  incorrect          no
4    3     missed         yes
5    3     missed         yes
6    2    correct          no
7    4       pass        pass
0 голосов
/ 05 февраля 2019

Попробуйте:

df.groupby('key')['type'].transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))

Вывод:

0    False
1    False
2    False
3    False
4     True
5     True
6    False
7    False
Name: type, dtype: bool

И вы можете замаскировать 'pass':

df.groupby('key')['type']\
  .transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))\
  .mask(df.type == 'pass','pass')

Вывод:

0    False
1    False
2    False
3    False
4     True
5     True
6    False
7     pass
Name: type, dtype: object

И, замените True / False на yes / no:

df.groupby('key')['type']\
  .transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))\
  .replace({False:'No',True:'Yes'})\
  .mask(df.type == 'pass','pass')

Выход:

0      No
1      No
2      No
3      No
4     Yes
5     Yes
6      No
7    pass
Name: type, dtype: object

Назначить столбцу данных:

df['only_misses'] = df.groupby('key')['type']\
                      .transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))\
                      .replace({False:'No',True:'Yes'})\
                      .mask(df.type == 'pass','pass')
df

Выход:

   key       type only_misses
0    1    correct          No
1    1  incorrect          No
2    2     missed          No
3    2  incorrect          No
4    3     missed         Yes
5    3     missed         Yes
6    2    correct          No
7    4       pass        pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...