合并两个 csv 文件,为所有匹配的记录添加一个带有标志值的列

Posted

技术标签:

【中文标题】合并两个 csv 文件,为所有匹配的记录添加一个带有标志值的列【英文标题】:Merge two csv files, add a column with a flag value for all matched records 【发布时间】:2021-09-19 03:59:38 【问题描述】:

我有两个包含数据的 csv 文件,我想匹配它们,并在它们匹配时添加一个包含标志值的列。第一个文件是包含所有患者的“主”文件,第二个文件包含已签名的文档 ID。

文件 1 的内容:

recid  visit   docid
1      arm1    1012
2      arm1    1023
3      arm1    1024
4      arm1    1026
5      arm1    1028
6      arm1    1031
7      arm1    1037
8      arm1    1040

文件 2 的内容:

docid
1023
1024
1028

所需的输出文件:

recid  visit   docid  match
1      arm1    1012   
2      arm1    1023   1
3      arm1    1024   1
4      arm1    1026
5      arm1    1028   1
6      arm1    1031
7      arm1    1037
8      arm1    1040

这是我目前得到的代码:

import pandas as pd

# which file to read
IN_FILE1 = "patients.txt"
IN_FILE2 = "informedconsent.txt"
OUT_FILE = "output_matched.csv"
 
# load data from csv files
df_file1 = pd.read_csv (IN_FILE1, sep = "\t")
df_file2 = pd.read_csv (IN_FILE2, sep = "\t")

# merge on docid
df_merge = df_file1.merge(df_file2, on='docid', how='left')

# flag the matches
if df_merge['docid'].empty:
    df_merge['matched'] = ""
else: 
    df_merge['matched'] = "1"

print(df_merge) #test

# write to file
df_merge.to_csv (OUT_FILE, sep = "\t", index = False, header=True)

问题显然是它被合并到docid 列上,所以它永远不会为空。但是第二个文件只包含一列,因此没有添加新列,否则我可以检查那些新列或其他内容。

如果我将其更改为how='inner',那么它可以工作,但我只能得到匹配项,但结果需要是第一个文件的所有记录,即使它们不匹配。

当我编辑 file2 并将列名更改为 docid2 并将代码更改为:

df_merge = df_file1.merge(df_file2, left_on='docid', right_on='docid2', how='left')

if df_merge['docid2'].empty:
    # etc..

它添加了一个docid2 列,该列仅在匹配时包含一个 guid 值,所以这是正确的。但是matched 列仍然始终包含“1”。

关于如何做到这一点的任何想法?

【问题讨论】:

【参考方案1】:

merge 带指示器:

df3 = df1.merge(df2, on='docid', how='left', indicator='match')

df3:

   recid visit  docid      match
0      1  arm1   1012  left_only
1      2  arm1   1023       both
2      3  arm1   1024       both
3      4  arm1   1026  left_only
4      5  arm1   1028       both
5      6  arm1   1031  left_only
6      7  arm1   1037  left_only
7      8  arm1   1040  left_only

然后map进行数值转换:

df3['match'] = df3['match'].map('both': 1, 'left_only': '')

df3:

   recid visit  docid match
0      1  arm1   1012      
1      2  arm1   1023     1
2      3  arm1   1024     1
3      4  arm1   1026      
4      5  arm1   1028     1
5      6  arm1   1031      
6      7  arm1   1037      
7      8  arm1   1040      

或不带merge 通过np.whereisin

df1['match'] = np.where(df1['docid'].isin(df2['docid']), 1, '')

df1:

   recid visit  docid match
0      1  arm1   1012      
1      2  arm1   1023     1
2      3  arm1   1024     1
3      4  arm1   1026      
4      5  arm1   1028     1
5      6  arm1   1031      
6      7  arm1   1037      
7      8  arm1   1040      

【讨论】:

感谢您的彻底回答,但最终方法给出错误“NameError:名称'np'未定义”,当我将np.更改为df_file1.时,我得到“For argument”就地" 预期类型 bool,接收类型 str。" numpypandas 的依赖库,您需要将其导入import numpy as np,但如果安装了pandas,则numpy 也是如此【参考方案2】:

你可以使用.isin():

df_file1['match'] = (df_file1['docid'].isin(df_file2['docid'])*1).replace(0,'')

print(df_file1)

   recid visit  docid match
0      1  arm1   1012      
1      2  arm1   1023     1
2      3  arm1   1024     1
3      4  arm1   1026      
4      5  arm1   1028     1
5      6  arm1   1031      
6      7  arm1   1037      
7      8  arm1   1040  

【讨论】:

感谢您的快速回答,有很多答案,我接受了另一个。 .isin 听起来是正确的做法。 @BdR 非常欢迎您。我了解到您选择了多个.isin()solutions 中的一个答案,请注意认为这个答案是最紧凑的,也是最早使用.isin 的答案。如果您因为可读性而选择另一个,我会理解的。编码愉快!【参考方案3】:

使用isin + astype + replace

df_parent['match'] = df_parent['docid'].isin(df_docid['docid']).astype(int).replace(0, '')

输出:

  recid visit  docid match
0   1   arm1    1012    
1   2   arm1    1023    1
2   3   arm1    1024    1
3   4   arm1    1026    
4   5   arm1    1028    1
5   6   arm1    1031    
6   7   arm1    1037    
7   8   arm1    1040    

【讨论】:

感谢您的快速回答,.isin 正是我想要的。虽然我不认为我会弄清楚所需的类型转换。

以上是关于合并两个 csv 文件,为所有匹配的记录添加一个带有标志值的列的主要内容,如果未能解决你的问题,请参考以下文章

如何把多个CSV文件的数据变成一个EXCEL表格

如何从命令行合并两个 CSV 文件?

使用 csv 文件中的所有信息生成在两个标签之间合并的所有合并请求的列表

将 CSV 文件与批处理文件合并,包括每行中的文件名

如何将多个 csv 文件合并为一个 csv 文件

如何根据字段合并两个 CSV 文件并在每条记录上保持相同数量的属性?