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