繁体   English   中英

如何使用列表理解来查找所有 Pandas 数据帧共有的列

[英]How to use list comphrehension to find columns common to all Pandas dataframes

我需要找到所有 5 个不同 Pandas 数据帧中的所有列。 目前我正在使用这样的代码:

dfs = [df0, df1, df2, df3, df4]

cols = dfs[0].columns
for df in dfs[1:]:
    cols &= df.columns

假设这段代码是正确的,我想知道是否可以在列表理解中执行此操作,如果没有,是否有更有效或更简洁的方式来获得相同的结果。

我们有 reduce 来处理这个可以与Index.intersection一起使用的,很像 set.intersection:

from functools import reduce
reduce(pd.Index.intersection,[i.columns for i in dfs])

虚拟示例:

df1 = pd.DataFrame(columns=list('ABCDE'))
df2 = pd.DataFrame(columns=list('ABDE'))
from functools import reduce
dfs = [df1,df2]
reduce(pd.Index.intersection,[i.columns for i in dfs])
#Index(['A', 'B', 'D', 'E'], dtype='object')

If you really want to work with regular Python sets, you can pass in a lambda function that returns the intersection of two sets to the reduce function:

from functools import reduce

dfs = [df0, df1, df2, df3, df4]  # list of pandas DataFrames
columns_in_common = reduce(  # a Python set
    lambda s1, s2: s1.intersection(s2),
    (set(df) for df in dfs)
)

虽然我同意pd.Index.Intersection在处理 pandas 数据帧时更有意义。

编辑:

为了完整起见,这里有一种使用实际列表推导式的方法——尽管我们仅仅依靠其在单行中迭代序列的“副作用”而严重滥用了列表推导式。 我再说一遍:这不是构建列表推导的目的:它们应该只用于一件事且仅用于一件事,即构建一个列表

result = []

_ = [
    result.append(colname) 
    if (
        colname not in result 
        and all(
            colname in df.columns 
            for df in dfs
    ) 
    else None 
    for df in dfs 
    for colname in df.columns
]

在这里,列表_ (列表理解的结果)并不重要。 重要的是值是否已附加到result列表中,具体取决于它们是否出现在所有 DataFrame 列中,以及它们是否不存在于result列表本身中。

除了不必要的复杂之外,列表理解也比集合版本慢(可能是由于其中的三重 for 循环,也可能是由于 Python 列表中的搜索比 Python 集合慢)。 这是一个简单的测试用例:

>>> timeit.timeit("import functools;lists=[[1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 6]];functools.reduce(lambda s1, s2: s1.intersection(s2), (set(s) for s in lists))")
1.8992446570046013

列表理解

>>> timeit.timeit("mylist=[];lists=[[1, 2, 3], [2, 3, 4, 5], [4, 5, 6, 6]];[mylist.append(e) if e not in mylist and all(e in sublist for sublist in lists) else None for slist in lists for e in slist]")
6.89644429100008

为什么我们不能简单地将 append 新列名添加到在列表理解中创建的同一列表的真正答案? 是因为我们没有对它的引用——无论如何,在列表理解本身完成之前。 我们需要该引用才能从列表推导式创建列表,其逻辑比简单的 if/else 语句更复杂。

tl;博士如果您的列表创建逻辑不是简单的 if/else 测试,那么您不能真正使用列表推导来现场创建新列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM