检查一个数据框列是否是另一个列的子集



我有一个包含Enrolled_MonthsEligible_Months列的数据框,描述如下:

month_list1 = [
[(1, 2018), (2, 2018), (3, 2019)],
[(7, 2018), (8, 2018), (10, 2018)],
[(4, 2018), (5, 2018), (7, 2018)],
[(1, 2019), (2, 2019), (4, 2019)]
]
month_list2 = [
[(2, 2018), (3, 2019)],
[(7, 2018), (8, 2018)],
[(2, 2018), (3, 2019)],
[(10, 2018), (11, 2019)]
]
EID = [1, 2, 3, 4]
df = pd.DataFrame({
'EID': EID,
'Enrolled_Months': month_list1,
'Eligible_Months': month_list2
})
df
Out[6]: 
EID                     Enrolled_Months           Eligible_Months
0    1   [(1, 2018), (2, 2018), (3, 2019)]    [(2, 2018), (3, 2019)]
1    2  [(7, 2018), (8, 2018), (10, 2018)]    [(7, 2018), (8, 2018)]
2    3   [(4, 2018), (5, 2018), (7, 2018)]    [(2, 2018), (3, 2019)]
3    4   [(1, 2019), (2, 2019), (4, 2019)]  [(10, 2018), (11, 2019)]

我想创建一个名为Check的新列,如果Enrolled_Months包含Eligible_Months的所有元素,则该列为真。我想要的输出如下:

Out[8]: 
EID                     Enrolled_Months           Eligible_Months  Check
0    1   [(1, 2018), (2, 2018), (3, 2019)]    [(2, 2018), (3, 2019)]   True
1    2  [(7, 2018), (8, 2018), (10, 2018)]    [(7, 2018), (8, 2018)]   True
2    3   [(4, 2018), (5, 2018), (7, 2018)]    [(2, 2018), (3, 2019)]  False
3    4   [(1, 2019), (2, 2019), (4, 2019)]  [(10, 2018), (11, 2019)]  False

我试过以下方法:

df['Check'] = set(df['Eligible_Months']).issubset(df['Enrolled_Months'])

但最终得到错误TypeError: unhashable type: 'list'

有什么想法,我怎么才能做到这一点?

旁注:Enrolled_Months数据最初的格式非常不同,每个月都有自己的二进制列,而单独的Year列指定年份(在我看来真是糟糕的设计)。我创建了列表列,因为我认为它更容易使用,但请让我知道原始格式是否更适合我想要实现的目标。

您可以使用df.apply()创建新列:

df['Check'] = df.apply(
lambda row: set(row['Eligible_Months']).issubset(row['Enrolled_Months']), axis=1
)

这个输出:

EID                     Enrolled_Months           Eligible_Months  Check
0    1   [(1, 2018), (2, 2018), (3, 2019)]    [(2, 2018), (3, 2019)]   True
1    2  [(7, 2018), (8, 2018), (10, 2018)]    [(7, 2018), (8, 2018)]   True
2    3   [(4, 2018), (5, 2018), (7, 2018)]    [(2, 2018), (3, 2019)]  False
3    4   [(1, 2019), (2, 2019), (4, 2019)]  [(10, 2018), (11, 2019)]  False

您可以使用几个explodes,然后evalany:

df['Check'] = df.explode('Eligible_Months').explode('Enrolled_Months').eval('Enrolled_Months == Eligible_Months').groupby(level=0).any()

输出:

>>> df
EID                     Enrolled_Months           Eligible_Months  Check
0    1   [(1, 2018), (2, 2018), (3, 2019)]    [(2, 2018), (3, 2019)]   True
1    2  [(7, 2018), (8, 2018), (10, 2018)]    [(7, 2018), (8, 2018)]   True
2    3   [(4, 2018), (5, 2018), (7, 2018)]    [(2, 2018), (3, 2019)]  False
3    4   [(1, 2019), (2, 2019), (4, 2019)]  [(10, 2018), (11, 2019)]  False

列表推导可以正常工作:

df.assign(check = [set(l).issuperset(r) 
for l, r in 
zip(df.Enrolled_Months, df.Eligible_Months)])
EID                     Enrolled_Months           Eligible_Months  check
0    1   [(1, 2018), (2, 2018), (3, 2019)]    [(2, 2018), (3, 2019)]   True
1    2  [(7, 2018), (8, 2018), (10, 2018)]    [(7, 2018), (8, 2018)]   True
2    3   [(4, 2018), (5, 2018), (7, 2018)]    [(2, 2018), (3, 2019)]  False
3    4   [(1, 2019), (2, 2019), (4, 2019)]  [(10, 2018), (11, 2019)]  False

最新更新