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

Merge two csv files, add a column with a flag value for all matched records

我有两个包含数据的 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”。

关于如何做到这一点有什么想法吗?

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.where and isin:

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      

你可以使用 .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 + 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