我有一个制表符分隔的 ICD 代码矩阵文本文件 A.tsv,其中列是患者 ID 和 ICD 代码,行是每个患者的观察结果。 NA表示icd代码未诊断患者
study_id 691.8 692.9 701.2 706.1
a1 1 NA NA 2
a2 NA NA NA NA
a3 NA NA 1 NA
和一个包含感兴趣的 icd 代码的 icd_code 文件
691.8 ICD_9
706.1 ICD_10
对于患者,如果任何 ICD 感兴趣代码有值(非 NA),则诊断编码为 1。如果所有 ICD 感兴趣代码均为 NA,则诊断编码为 0。
对于上面的例子,输出应该是
study_id diagnosis
a1 1
a2 0
a3 0
对于上面的例子,输出应该是
study_id diagnosis
a1 1
a2 0
a3 0
我是 bash 脚本的新手,我不知道应该从哪里开始。如何用awk编写bash脚本来实现上述问题?
现在我有了一个解决方案,但它似乎总结了所有列,但没有总结 icd 文件中列出的感兴趣的特定 icd 代码
awk -F"\t" 'BEGIN { OFS="\t"; } NR==FNR { icd_codes[$1] = $2; next; } FNR > 1 { study_id = $1; diagnosis = 0; for (i = 2; i <= NF; i++) { if ($i != "NA" && icd_codes[$i] != "") { diagnosis = 1; break; } } print study_id, diagnosis; }' "$icd_file" "$input_file" > "$output_file"
最佳答案
脚本中的主要问题是 icd_codes[$i] != ""
应该使用列标题字符串,例如691.8
,作为数组索引,但使用该列单元格中的当前值,例如1
或 NA
。您需要一个额外的数组来从列号映射到列标题字符串,或者更有效地从列标题字符串到列号映射,因为它在每个输入行使用更少的循环迭代,就像我在下面所做的那样。
使用任何 awk:
$ cat tst.awk
BEGIN { OFS="\t" }
NR==FNR {
tgtIcds[$1]
next
}
FNR == 1 {
for ( fldNr=2; fldNr<=NF; fldNr++ ) {
icd = $fldNr
if ( icd in tgtIcds ) {
icds2fldNrs[icd] = fldNr
}
}
diag = "diagnosis"
}
FNR > 1 {
diag = 0
for ( icd in icds2fldNrs ) {
fldNr = icds2fldNrs[icd]
if ( $fldNr != "NA" ) {
diag = 1
break
}
}
}
{ print $1, diag }
$ awk -f tst.awk icd_file A.tsv
study_id diagnosis
a1 1
a2 0
a3 0
$ awk -f tst.awk icd_file input_file | column -t
study_id diagnosis
a1 1
a2 0
a3 0
关于bash - 使用 awk 为患者识别疾病,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76693132/