我是Python和熊猫的新手。我有一个具有以下结构的数据集。这是一只熊猫DF
city time1 time2
a [1991, 1992, 1993] [1993,1994,1995]
time1和time2在两个来源中重新表示数据的覆盖范围。我想创建一个新列,指示time1和time2是否有任何交集,如果是,则返回True,否则返回False。这项任务听起来非常简单。我正在考虑在两列上使用set操作,但它没有按预期工作。有人会帮我解决这个问题吗?
谢谢!
感谢您的帮助。
答案 0 :(得分:3)
您可以遍历所有列并将列表更改为集合,并查看交集中是否有任何值。
df1 = df.applymap(lambda x: set(x) if type(x) == list else set([x]))
df1.apply(lambda x: bool(x.time1 & x.time2), axis=1)
这是一种半矢量化的方式,可以让它运行得更快。
df1 = df[['time1', 'time2']].applymap(lambda x: set(x) if type(x) == list else set([x]))
(df1.time1.values & df1.time2.values).astype(bool)
甚至更快一点
change_to_set = lambda x: set(x) if type(x) == list else set([x])
time1_set = df.time1.map(change_to_set).values
time2_set = df.time2.map(change_to_set).values
(time1_set & time2_set).astype(bool)
答案 1 :(得分:2)
这是一种丑陋但矢量化的方法:
In [37]: df
Out[37]:
city time1 time2
0 a [1970] [1980]
1 b [1991, 1992, 1993] [1993, 1994, 1995]
2 c [2000, 2001, 2002] [2010, 2011]
3 d [2015, 2016] [2016]
In [38]: df['x'] = df.index.isin(
...: pd.DataFrame(df.time1.tolist())
...: .stack().reset_index(name='x')
...: .merge(pd.DataFrame(df.time2.tolist())
...: .stack().reset_index(name='x'),
...: on=['level_0','x'])['level_0'])
...:
In [39]: df
Out[39]:
city time1 time2 x
0 a [1970] [1980] False
1 b [1991, 1992, 1993] [1993, 1994, 1995] True
2 c [2000, 2001, 2002] [2010, 2011] False
3 d [2015, 2016] [2016] True
<强>定时:强>
In [54]: df = pd.concat([df] * 10**4, ignore_index=True)
In [55]: df.shape
Out[55]: (40000, 3)
In [56]: %%timeit
...: df.index.isin(
...: pd.DataFrame(df.time1.tolist())
...: .stack().reset_index(name='x')
...: .merge(pd.DataFrame(df.time2.tolist())
...: .stack().reset_index(name='x'),
...: on=['level_0','x'])['level_0'])
...:
1 loop, best of 3: 253 ms per loop
In [57]: %timeit df.apply(lambda x: bool(set(x.time1) & set(x.time2)), axis=1)
1 loop, best of 3: 5.36 s per loop