问题描述
df1 = pd.DataFrame({'type': ['cst1','cst1','cst2','cst3','cst3'],'year':[2017,2018,2019,2020,2017,2020]})
type year
0 cst1 2017
1 cst1 2018
2 cst1 2019
3 cst1 2020
4 cst2 2018
5 cst2 2019
6 cst2 2020
7 cst3 2017
8 cst3 2018
9 cst3 2019
10 cst3 2020
对于上述数据框需要检查每个类型值是否存在于所有四年 [2017,2020] 需要标记为 1,否则为 0。 例如:第一种类型 cst1 出现在所有 4 年中,因此标记为 1,cst2 仅出现在 3 年中,因此标记为 1。 注意:理想情况下,只包含四年,即 2017 - 2020。类型和年份组合将是唯一的。
期望输出:
type year label
0 cst1 2017 1
1 cst1 2018 1
2 cst1 2019 1
3 cst1 2020 1
4 cst2 2018 0
5 cst2 2019 0
6 cst2 2020 0
7 cst3 2017 1
8 cst3 2018 1
9 cst3 2019 1
10 cst3 2020 1
解决方法
如果所有年份都在 2017 年 -2020 年的范围内,我想 groupby/transform with nunique 可以:
df['label'] = (df1.groupby('type').transform('nunique') == 4).astype(int)
替代方案:
df1['label'] = 0
def test(x):
return set(x.values) == {2017,2018,2019,2020}
df1.iloc[df1.groupby('type')['year'].filter(test).index,2] = 1
,
- 使用
groupby()
根据类型创建组
- 使用
transform()
根据组获取每行中的年元组
- 将这些元组与您所需的年份进行比较。它将为每一行结果 True/False。
- 使用
astype('int')
将布尔值 (True/False) 转换为整数 (1/0)
required = (2017,2020)
df1["label"] = (df1.groupby('type').transform(tuple)["year"] == required).astype('int')
print(df1)
type year label
0 cst1 2017 1
1 cst1 2018 1
2 cst1 2019 1
3 cst1 2020 1
4 cst2 2018 0
5 cst2 2019 0
6 cst2 2020 0
7 cst3 2017 1
8 cst3 2018 1
9 cst3 2019 1
10 cst3 2020 1
,
让我们试试:
- 一个 groupby transform 用于测试每个组的年份是否是所需年份的子集。
- 使用
astype(int)
将布尔值转换为 1 和 0
import pandas as pd
df1 = pd.DataFrame({'type': ['cst1','cst1','cst2','cst3','cst3'],'year': [2017,2020,2017,2020]})
years = {2017,2020}
df1['label'] = (
df1.groupby('type').year.transform(lambda x: years.issubset(x))
).astype(int)
print(df1)
df1
:
type year label
0 cst1 2017 1
1 cst1 2018 1
2 cst1 2019 1
3 cst1 2020 1
4 cst2 2018 0
5 cst2 2019 0
6 cst2 2020 0
7 cst3 2017 1
8 cst3 2018 1
9 cst3 2019 1
10 cst3 2020 1
*注意这将匹配至少四年的任何组。因此,如果一个组包含来自 [2016,2020] 的条目,它将被匹配。