【问题标题】:How to compare a specific column in two csv files and output differences to a third file如何比较两个 csv 文件中的特定列并将差异输出到第三个文件
【发布时间】:2020-02-05 15:23:29
【问题描述】:

我有两个名为 test1.csv 和 test2.csv 的 csv 文件,它们都有一个名为“名称”的列。我想比较两个文件之间的 Name 列中的每一行,并将不匹配的行输出到第三个文件。我看过一些使用熊猫的例子,但没有一个适合我的情况。任何人都可以帮我写一个脚本吗?

Test2 将被更新以包含来自 test1 的所有值以及未包含在 test1 中的新值(这是我想要保存到第三个文件中的值)

列的外观示例如下:

test1.csv:

Name     Number    Status
gfd454   456       Disposed
3v4fd    521       Disposed
th678iy  678       Disposed

test2.csv

Name     Number    Status
gfd454   456       Disposed
3v4fd    521       Disposed
th678iy  678       Disposed
vb556h   665       Disposed    

【问题讨论】:

  • 你的两列长度相等吗?还是有一些标识符可以用来匹配它们?提供一些样本数据会很有用
  • @Dan 不幸的是,它们的长度不相等。该列得到更新,因此在每个新文件中添加了更多内容。我希望它只在第三个文件中包含新的。
  • @pythonscrub 你是否认为 test2.csv 会添加更多名称并且你想找到它们?
  • @Dan 添加了一个带有额外值的列示例,由于它与 test1 文件输出不匹配,因此我想将其移至第三个文件。
  • @balderman 是的,test2 将包括来自 test1 的所有值以及我想要保存到第三个文件的新值。

标签: python pandas csv difference


【解决方案1】:

见下文。

想法是将名称读入s python set 数据结构,并通过set substruction找到新名称。

1.csv:

Name Number
A 12
B 34 
C 45 

2.csv

Name Number
A 12
B 34
C 45
D 77
Z 67

下面的代码将打印新名称 {'D', 'Z'}。

def read_file_to_set(file_name):
    with open(file_name) as f:
        return set(l.strip().split()[0] for x,l in enumerate(f.readlines()) if x > 0)



set_1 = read_file_to_set('1.csv')
set_2 = read_file_to_set('2.csv')
new_names = set_2 - set_1
print(new_names)

【讨论】:

  • 这会返回所有值,而不仅仅是新值。这可能是什么原因?
  • @pythonscrub 我认为你错了。请参阅我的扩展答案。
  • 文件中不止一列,所以也许这就是它返回更多信息的原因?我可以将其设置为仅检查两个文件中的“名称”列吗?
  • @pythonscrub 请分享文件#1中的几行“真实”行和文件#2中的几行
  • 如果分隔符是空格 - 代码应该“按原样”工作。如果不是 - 您应该找出它是什么并将其添加到 split() 函数调用中。您是否针对您的文件测试了最新代码?
【解决方案2】:

此答案假定数据按照您的示例排列:

import pandas as pd

# "read" each file
df1 = pd.DataFrame({'Name': ['gfd454', '3v4fd', 'th678iy']})
df2 = pd.DataFrame({'Name': ['gfd454', '3v4fd', 'th678iy', 'fdvs']})

# make column names unique
df1 = df1.rename(columns={'Name': 'Name1'})
df2 = df2.rename(columns={'Name': 'Name2'})

# line them up next to each other
df = pd.concat([df1, df2], axis=1)

# get difference
diff = df[df['Name1'].isnull()]['Name2']  # or df[df['Name1'] != df['Name2']]['Name2']

# write
diff.to_csv('test3.csv')

【讨论】:

  • 问题是新的会不断添加到 test2,所以我无法制作硬编码的数据框。
  • 是的,将pd.DataFrame 调用替换为pd.read_csv。我刚刚创建了虚拟数据以便代码运行。
  • 如果在列末尾添加添加的值,则此方法可以正常工作。有什么方法可以检测到附加值,即使它在某处的列中随机出现?
  • 在这种情况下,您可能应该使用set() 方法
  • 你能举个例子吗?很抱歉给您带来麻烦,我是新手,希望更好地了解这一切
【解决方案3】:

这应该是直截了当的 - 解决方案假定 file2 的内容相同或更长,因此项目仅附加到 file2。

import pandas as pd

df1 = pd.read_csv(r"C:\path\to\file1.csv")
df2 = pd.read_csv(r"C:\path\to\file2.csv")

# print(df1)
# print(df2)

df = pd.concat([df1, df2], axis=1)

df['X'] = df['A'] == df['B']
print(df[df.X==False])

df3 = df[df.X==False]['B']
print(df3)
df3.to_csv(r"C:\path\to\file3.csv")

如果项目是任意顺序的,你可以使用df.isin()如下:

import pandas as pd

df1 = pd.read_csv(r"C:\path\to\file1.csv")
df2 = pd.read_csv(r"C:\path\to\file2.csv")

df = pd.concat([df1, df2], axis=1)

df['X'] = df['B'].isin(df['A'])
df3 = df[df.X==False]['B']
df3.to_csv(r"C:\path\to\file3.csv")

我创建了以下 2 个文件:

A
1_in_A
2_in_A
3_in_A
4_in_A

和file2.csv:

B
2_in_A
1_in_A
3_in_A
4_in_B
5_in_B

用于测试。数据框df 如下所示:

|    | A      | B      | X     |
|---:|:-------|:-------|:------|
|  0 | 1_in_A | 2_in_A | True  |
|  1 | 2_in_A | 1_in_A | True  |
|  2 | 3_in_A | 3_in_A | True  |
|  3 | 4_in_A | 4_in_B | False |
|  4 | nan    | 5_in_B | False |

我们只选择标记为False的项目。

【讨论】:

  • 可以说这些项目是任意顺序的。那么代码会是什么样子?
  • 我修改了答案以反映您的评论。
猜你喜欢
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多