如何保留具有公共列值的多个数据框中的行?

How to retain rows from multiple dataframes with common column value?

假设我有多个数据帧:

print (df1)
                datetime    A
0       2012-08-14 07:00    1
1       2012-08-14 07:01    2
2       2012-08-14 08:15    3
                     ...  ...
192908  2013-08-14 16:00  600
192948  2013-08-14 16:15  700
192949  2013-08-14 16:57  900

print (df2)
               datetime    B    
0      2012-08-14 07:00  100
1      2012-08-14 07:15  200
2      2012-08-14 07:30  300
                    ...  ...
12140  2013-09-24 15:45   50
12141  2013-09-24 16:00   60
12142  2013-09-24 16:15   70

如何创建一个新的 df,其中仅包含在同一日期时间 AB 列中有值的行?我尝试使用 isin 函数:

df1 = df1[df1['date'].isin(df2['date'])]

但这只会进行单向检查,即仅保留 A 的值,同时存在 B 的值 datetime,但如果存在BA 中不存在的日期时间的额外值,然后这些值留在 df2.[​​=23=] 中

我可以反方向重复操作来解决:

df2 = df2[df2['date'].isin(df1['date'])]

但是对于 >2 个数据帧(我目前的工作中大约有 50 个),这变得非常长且效率低下,因为有必要遍历完整数据帧集之间的所有可能的配对组合。例如,第三个数据帧 df3 首先需要针对 df1 和 df2 进行检查,但是如果它包含的日期时间既不存在于 df1 中也不存在于 df2 中,那么 df1 和 df2 又需要针对 df3 进行重新检查。

期望的输出是重新定义所有数据帧,使它们仅包含 AB 等具有匹配日期时间值的值。

这是一个连接/合并操作。标准 Codd 关系 theory/algebra.

import io
df1 = pd.read_csv(io.StringIO("""                datetime    A
0       2012-08-14 07:00    1
1       2012-08-14 07:01    2
2       2012-08-14 08:15    3
192908  2013-08-14 16:00  600
192948  2013-08-14 16:15  700
192949  2013-08-14 16:57  900"""), sep="\s\s+", engine="python")

df2 = pd.read_csv(io.StringIO("""               datetime    B    
0      2012-08-14 07:00  100
1      2012-08-14 07:15  200
2      2012-08-14 07:30  300
12140  2013-09-24 15:45   50
12141  2013-09-24 16:00   60
12142  2013-09-24 16:15   70"""), sep="\s\s+", engine="python")

pd.merge(df1,df2, on="datetime", how="inner")

输出

    datetime    A   B
0   2012-08-14 07:00    1   100

想要合并多个数据框

import io, random, functools

# generate a list of dataframes for merge... start with two sample ones
dfs = [df1, df2]
# generate longer list of dataframes, rename columns to add some interest for merge :-)
dfs = [dfs[random.randint(0, len(dfs)-1)].pipe(lambda d: d.rename(columns={d.columns[1]:f"{d.columns[1]}_{i}"})) for i in range(8)]

# and one line merge the whole list of dataframes
functools.reduce(lambda left,right: pd.merge(left,right,on='datetime'), dfs)

datetime A_0 B_1 B_2 B_3 A_4 B_5 B_6 A_7
0 2012-08-14 07:00 1 100 100 100 1 100 100 1