#python #pandas #if-statement #lambda #filter
#python #pandas #if-оператор #лямбда #Фильтр
Вопрос:
У меня есть следующий фрейм данных, который представляет номер сотрудника, отдел, в котором они находятся, и код их роли в компании, который может быть «1» или «2». В столбце «Название отдела» вы можете указать отдел, в котором у сотрудника есть своя роль (соглашение об именовании «XX: название отдела», где XX — код страны), или, в случае, если у сотрудника есть эта роль для всей страны, вместо названия отдела вы найдете имястрана, в которой у сотрудника есть роль. Фрейм данных будет выглядеть следующим образом:
Department Name Employee Number Role Code
0 AU:Dept1 1000 1
1 All Australia 1000 2
2 AU:Dept7 1000 1
4 CZ:Dept3 1001 2
5 CZ:Dept3 1001 1
6 CZ:Dept4 1001 1
7 All Poland 1002 1
8 PL:Dept1 1002 2
9 PL:Dept2 1002 1
10 ES:Dept1 1002 2
11 All Singapore 1003 1
12 All Singapore 1003 2
Сотрудники могут иметь либо только роль 1, либо роль 2 в каждом уникальном названии отдела, и, если роль предназначена для всей страны, это означает, что у этого человека есть роль для всех отделов в этой стране. Тем не менее, как вы можете видеть в примере, у нас могут быть сотрудники, у которых в базе данных есть роль, назначенная «всей стране», но также и определенному отделу этой страны (например, роль 1 для «Всей Польши», но также роль 1 для отдела в Польше, как вы можетесмотрите Пример, который был бы избыточным и также должен быть помечен).
Мне нужно создать код, который возвращал бы строки, которые имеет номер сотрудника:
- Роль 1 и роль 2 в одном отделе
- Роль 1 и роль 2 для всей страны
- Роль 1 для всей страны и роль 2 в любом отделе этой страны
- Роль 2 для всей страны и роль 1 в любом отделе этой страны
В этом случае вывод будет выглядеть следующим образом (возвращая все строки, вызывающие нарушения)
Department Name Employee Number Role Code
0 AU:Dept1 1000 1
1 All Australia 1000 2
2 AU:Dept7 1000 1
4 CZ:Dept3 1001 2
5 CZ:Dept3 1001 1
7 All Poland 1002 1
8 PL:Dept1 1002 2
9 PL:Dept2 1002 1
11 All Singapore 1003 1
12 All Singapore 1003 2
Каков наилучший способ сделать это?
Комментарии:
1. Это своего рода небольшая реализация, а не краткий вопрос, и его можно решить путем исследования различных более мелких проблем. В будущем, пожалуйста, включайте свой код, чтобы читатели могли оценить, в какой части алгоритма у вас возникают проблемы, и соответствующим образом сфокусировать ответы.
Ответ №1:
Вы можете создавать новые столбцы, разделяя страну и отдел. Затем правила могут быть применены с помощью комбинации логических масок, но вторая часть довольно сложная … следите за комментариями.
import pycountry
### double roles for same department
# (treat 'all <country>' as just another department)
m1 = (
df.groupby(['Department_Name', 'Employee_Number'])
.transform('count').squeeze()
> 1
)
### mismatched roles for the entire country and at least one department
# split country codes and department names
df[['country_code', 'dept']] = [
[pycountry.countries.get(name=dn.split()[1]).alpha_2, 'All']
if dn.startswith('All') else dn.split(':')
for dn in df['Department_Name'].to_list()
]
# return all rows for each country-employee if a flag is found
flag = []
for (cc, en), g in df.groupby(['country_code', 'Employee_Number']):
subroles = g.loc[g['dept'].ne('All'), 'Role_Code'].to_list()
for rc in g.loc[g['dept'].eq('All'), 'Role_Code']:
other = 1 if rc==2 else 2
if other in subroles:
flag.append([cc, en, True])
break
# combine both rules
df = df.merge(
pd.DataFrame(flag, columns=['country_code', 'Employee_Number', 'flag']),
how='left', on=['country_code', 'Employee_Number']
)
flag = df.pop('flag')
flag = flag.where(flag, m1)
Используйте его как
df_out = df[flag]
print(df_out)
Department_Name Employee_Number Role_Code country_code dept
0 AU:Dept1 1000 1 AU Dept1
1 All Australia 1000 2 AU All
2 AU:Dept7 1000 1 AU Dept7
3 CZ:Dept3 1001 2 CZ Dept3
4 CZ:Dept3 1001 1 CZ Dept3
6 All Poland 1002 1 PL All
7 PL:Dept1 1002 2 PL Dept1
8 PL:Dept2 1002 1 PL Dept2
10 All Singapore 1003 1 SG All
11 All Singapore 1003 2 SG All
Комментарии:
1. Спасибо за подробное объяснение!