You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对比Google Cloud Bucket中多份CSV的DataFrame并提取非共同值?

问题描述

我在Google Cloud Bucket中存储了若干CSV文件,目标是对比每份文件中的ColumnA和ColumnB两列,输出那些并非在Bucket内所有CSV文件中都存在的值。目前我已能列出Bucket内的文件,通过循环将每份CSV读取为包含目标列的DataFrame并存储到字典中,但不清楚如何实现多DataFrame的对比提取。

现有代码如下:

import pandas as pd, numpy as np
import os
from google.cloud import storage

bucketName = 'test_bucket_01'
bucketFolder = 'test_folder_01'
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'test.credentials.json'
storage_client = storage.Client.from_service_account_json('test.credentials.json')
bucket = storage_client.get_bucket(bucketName)
file_location = f'gs://{bucketName}/{bucketFolder}'

storage_blob_list = list(storage_client.list_blobs(bucketName, prefix=bucketFolder))

file_list = [blob_name.name[len(bucketFolder):] for blob_name in storage_blob_list if blob_name.name != bucketFolder and 'String' in blob_name.name]
file_list = [element.replace("/","") for element in file_list]

for fileName in file_list:
    d = {}
    data = pd.read_csv(f'{file_location}/{fileName}',
            usecols=['ColumnA','ColumnB'])
    d[fileName1] = data
    print(d[fileName])

4份DataFrame的输出如下:

ColumnA      ColumnB
0  AA-1234  AA-1234-ABC
1  AA-1235  AA-1235-ABC
2  AA-1236  AA-1236-ABC
3  AA-1237  AA-1237-ABC
   ColumnA      ColumnB
0  AA-1234  AA-1234-ABC
1  AA-1235  AA-1235-ABC
2  AA-1236  AA-1236-ABC
3  BB-1237  BB-1237-ABC
   ColumnA      ColumnB
0  AA-1234  AA-1234-ABC
1  AA-1235  AA-1235-ABC
2  AA-1236  AA-1236-ABC
3  CC-1237  CC-1237-ABC
   ColumnA      ColumnB
0  AA-1234  AA-1234-ABC
1  AA-1235  AA-1235-ABC
2  AA-1236  AA-1236-ABC
3  DD-1237  DD-1237-ABC

请问最简单的实现提取并输出非所有DataFrame共有的值的方法是什么?


解决方案

先修正代码里的小问题

你当前的循环每次都会重新初始化字典d,导致最后只保留最后一个文件的数据,而且还有fileName1的笔误。先把字典初始化移到循环外面:

# 把字典初始化放在循环外
df_dict = {}
for fileName in file_list:
    df = pd.read_csv(f'{file_location}/{fileName}', usecols=['ColumnA','ColumnB'])
    df_dict[fileName] = df  # 修正笔误,用fileName作为键

方法一:统计出现次数(推荐,能看来源文件)

核心逻辑是:把所有DataFrame的行合并,统计每组(ColumnA, ColumnB)在多少个文件里出现,筛选出出现次数不等于文件总数的行。

完整代码:

import pandas as pd
import os
from google.cloud import storage

bucketName = 'test_bucket_01'
bucketFolder = 'test_folder_01'
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'test.credentials.json'
storage_client = storage.Client.from_service_account_json('test.credentials.json')
bucket = storage_client.get_bucket(bucketName)
file_location = f'gs://{bucketName}/{bucketFolder}'

storage_blob_list = list(storage_client.list_blobs(bucketName, prefix=bucketFolder))

file_list = [blob_name.name[len(bucketFolder):] for blob_name in storage_blob_list if blob_name.name != bucketFolder and 'String' in blob_name.name]
file_list = [element.replace("/","") for element in file_list]

# 存储所有DataFrame到字典
df_dict = {}
for fileName in file_list:
    df = pd.read_csv(f'{file_location}/{fileName}', usecols=['ColumnA','ColumnB'])
    df_dict[fileName] = df

# 合并所有DataFrame,标记来源文件
all_dfs = []
for name, df in df_dict.items():
    df['source_file'] = name
    all_dfs.append(df)
combined_df = pd.concat(all_dfs, ignore_index=True)

# 统计每组值在多少个文件中出现
count_df = combined_df.groupby(['ColumnA', 'ColumnB'])['source_file'].nunique().reset_index(name='file_count')

# 筛选出不是所有文件都有的行
total_files = len(file_list)
non_common_rows = count_df[count_df['file_count'] != total_files]

# 关联回原数据,查看这些值来自哪些文件
result = pd.merge(combined_df, non_common_rows, on=['ColumnA', 'ColumnB'])
print(result)

方法二:取交集反向筛选(更简洁,不需要来源文件)

如果只需要知道哪些值不是公共的,不需要追踪来源,可以用交集的方式:

# 接前面的df_dict初始化代码

# 先取第一个文件的行作为初始公共基准
common_rows = df_dict[next(iter(df_dict.keys()))].copy()

# 依次和其他文件取交集,最终得到所有文件共有的行
for df in df_dict.values():
    common_rows = pd.merge(common_rows, df, on=['ColumnA', 'ColumnB'], how='inner')

# 从所有行中排除公共行,得到非公共行
all_unique_rows = pd.concat(df_dict.values(), ignore_index=True).drop_duplicates()
non_common_rows = all_unique_rows.merge(common_rows, on=['ColumnA', 'ColumnB'], how='left', indicator=True)
non_common_rows = non_common_rows[non_common_rows['_merge'] == 'left_only'].drop('_merge', axis=1)

print(non_common_rows)

输出结果

针对你的示例数据,两种方法都会输出以下非公共行:

ColumnA      ColumnB
0  AA-1237  AA-1237-ABC
1  BB-1237  BB-1237-ABC
2  CC-1237  CC-1237-ABC
3  DD-1237  DD-1237-ABC

内容的提问来源于stack exchange,提问作者Pete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:55:23