在Pandas DataFrame中跨多个列映射方法

时间:2017-09-11 20:21:27

标签: python list pandas dataframe

我有一个Pandas数据框,其值是列表:

import pandas as pd

DF = pd.DataFrame({'X':[[1, 5], [1, 2]], 'Y':[[1, 2, 5], [1, 3, 5]]})
DF
         X          Y
0   [1, 5]  [1, 2, 5]
1   [1, 2]  [1, 3, 5]

我想检查X中的列表是否是Y中列表的子集。对于单个列表,我们可以使用set(x).issubset(set(y))执行此操作。但是我们如何在Pandas数据列中做到这一点呢?

到目前为止,我唯一想到的是使用单个列表作为解决方法,然后将结果转换回Pandas。对于这项任务来说似乎有点复杂:

foo = [set(DF['X'][i]).issubset(set(DF['Y'][i])) for i in range(len(DF['X']))]

foo = pd.DataFrame(foo)
foo.columns = ['x_sub_y']
pd.merge(DF, foo, how = 'inner', left_index = True, right_index = True)

         X          Y   x_sub_y
0   [1, 5]  [1, 2, 5]   True
1   [1, 2]  [1, 3, 5]   False

有没有更简单的方法来实现这一目标?可能使用.map.apply

3 个答案:

答案 0 :(得分:5)

选项1
转化setdifference使用np.where

df_temp = DF.applymap(set)
DF['x_sub_y'] = np.where(df_temp.X - df_temp.Y, False, True)
DF
        X          Y  x_sub_y
0  [1, 5]  [1, 2, 5]     True
1  [1, 2]  [1, 3, 5]    False

选项2
更快,astype转化

DF['x_sub_y'] = ~(DF.X.apply(set) - DF.Y.apply(set)).astype(bool)
DF 
        X          Y  x_sub_y
0  [1, 5]  [1, 2, 5]     True
1  [1, 2]  [1, 3, 5]    False

选项3
有趣np.vectorize

def foo(x):
     return not x

v = np.vectorize(foo)    
DF['x_sub_y'] = v(DF.X.apply(set) - DF.Y.apply(set)) 
DF
        X          Y  x_sub_y
0  [1, 5]  [1, 2, 5]     True
1  [1, 2]  [1, 3, 5]    False

使用相同的方法扩展Scott Boston's answer的速度:

def foo(x, y):
    return set(x).issubset(y)

v = np.vectorize(foo)

DF['x_sub_y'] = v(DF.X, DF.Y)
DF
        X          Y  x_sub_y
0  [1, 5]  [1, 2, 5]     True
1  [1, 2]  [1, 3, 5]    False

1000 loops, best of 3: 460 µs per loop           # Before       
10000 loops, best of 3: 103 µs per loop          # After

大( df * 10000

1 loop, best of 3: 1.26 s per loop               # Before   
100 loops, best of 3: 13.3 ms per loop           # After

答案 1 :(得分:4)

使用setissubset

DF.assign(x_sub_y = DF.apply(lambda x: set(x.X).issubset(set(x.Y)), axis=1))

输出:

        X          Y  x_sub_y
0  [1, 5]  [1, 2, 5]     True
1  [1, 2]  [1, 3, 5]    False

答案 2 :(得分:2)

或者您可以尝试set

DF['x_sub_y']=DF.X+DF.Y
DF['x_sub_y']=DF['x_sub_y'].apply(lambda x : list(set(x)))==DF.Y
DF
Out[691]: 
        X          Y  x_sub_y
0  [1, 5]  [1, 2, 5]     True
1  [1, 2]  [1, 3, 5]    False