【问题标题】:Categorize csv files based on $18 info and find the csv file in each category which has the largest unique number in $4根据 $18 信息对 csv 文件进行分类,并在每个类别中找到 $4 中唯一编号最大的 csv 文件
【发布时间】:2014-09-04 02:15:50
【问题描述】:

如果我们有三个示例输入文件:

Test_95_target_1334_assay_Detail3.csv

A,accession,result_id,cpd_number,lot_no,assay_id,alt_assay_id,version_no,result_type,type_desc,operator,result_value,unit_id,unit_value,unit_desc,batch_no,experiment_date,discipine,assay_name,activity_flag
95,PKC,123456,cpd-0123456,1,1334,5678,1,1,IC50,>,26.21,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Enzymatic,PBA,
95,PKC,123456,cpd-0123456,1,1334,4600,1,1,IC50,,17.1,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Enzymatic,PBA,
95,PKC,123456,cpd-1234567,1,1334,2995,1,1,Ki,,30,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Enzymatic,PBA,
95,PKC,123456,cpd-1234567,1,1334,2900,1,1,IC50,,30,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Enzymatic,PBA,

Test_95_target_1338_assay_Detail3.csv

A,accession,result_id,cpd_number,lot_no,assay_id,alt_assay_id,version_no,result_type,type_desc,operator,result_value,unit_id,unit_value,unit_desc,batch_no,experiment_date,discipine,assay_name,activity_flag
95,PKC,123456,cpd-0123456,1,1338,3999,1,1,IC50,,55,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Biochemical,PBA,
95,PKC,123456,cpd-0123456,1,1338,1985,1,1,IC50,,66,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Biochemical,PBA,
95,PKC,123456,cpd-1234007,1,1338,2995,1,1,Ki,,18,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Biochemical,PBA,
95,PKC,123456,cpd-1239867,1,1338,2900,1,1,IC50,,20,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Biochemical,PBA,
95,PKC,123456,cpd-1234567,1,1338,2900,1,1,IC50,,20,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Biochemical,PBA,

Test_95_target_2888_assay_Detail3

Test,accession,result_id,cpd_number,lot_no,assay_id,alt_assay_id,version_no,result_type,type_desc,operator,result_value,unit_id,unit_value,unit_desc,batch_no,experiment_date,discipine,assay_name,activity_flag
95,PKC,123456,cpd-0123456,1,2888,3830,1,1,IC50,>,24.49,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Cell,PBA,
95,PKC,123456,cpd-0123456,1,2888,4600,1,1,IC50,,19.6799,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Cell,PBA,
95,PKC,123456,cpd-1234567,1,2888,3830,1,1,IC50,,30,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Cell,PBA,
95,PKC,123456,cpd-5566778,1,2888,3830,1,1,IC50,,30,1,uM,micromolar,67682,1/24/2007 12:00:00AM,Cell,PBA,

有什么方法可以使用 bash/awk(也欢迎使用 python!)对第 18 列(18 美元)为“酶”、“生化”和“细胞”的文件进行分类?我们的目标是在 18 美元中从生化或酶中选择具有最多独特化合物(4 美元)的文件,并在 18 美元中选择具有来自细胞的独特化合物数量最多的文件。

在这种情况下,我们将从第 18 列为“酶”或“生化”的文件中选择“Test_95_target_1338_assay_Detail3.csv”。 (因为“Test_95_target_1338_assay_Detail3.csv”在 4 美元中有 3 个独特的化合物,而“Test_95_target_1334_assay_Detail3.csv”只有 2 个独特的化合物。3 > 2)在这种情况下,我们将为单元类别选择“Test_95_target_2888_assay_Detail3.csv”,因为它是唯一的一。

尝试在这里:此脚本将找到行数最多的 csv 文件,并将该文件名变成一个变量以用于以下过程。我有另一个脚本来查找具有最多独特化合物(4 美元)的 csv 文件。我将该脚本留在了另一台笔记本电脑中,明天早上才能访问它。因此,只需发布​​以下内容。

#!/bin/bash

for A in 95

do   

wc -l Test_${A}_target_*_assay_Detail_average.csv > Test_${A}_target.csv

### This will make

#4 Test_95_target_1334_assay_Detail3.csv
#4 Test_95_target_1338_assay_Detail3.csv
#4 Test_95_target_2388_assay_Detail3.csv
#13 Total

head -n -1 Test_${A}_target.csv > Test_${A}_target2.csv  # remove the last line "total"

sort -k1 -r -n Test_${A}_target2.csv > Test_${A}_target3.csv   # sort the count column

# Only pick the second column in the "wc -l" output

awk -F " " '{print $2}' Test_${A}_target3.csv > Test_${A}_target4.csv   # Grasp the $2 file name info

max=$(head -n 1 Test_${A}_target4.csv)   # Make the top file name as the variable "max" for the following process

echo $max

rm Test_${A}_target3.csv Test_${A}_target2.csv Test_${A}_target.csv

done

输出:

echo $max

Test_95_target_1338_assay_Detail3.csv

但是,我不太清楚如何根据 18 美元的信息对 csv 文件进行分类。任何大师都可以提供一些cmets或解决方案吗?谢谢。

【问题讨论】:

  • 提示:awk -F, '{print $18}' file 根据逗号分隔字段获取第 18 个字段。
  • .csv 文件有多大(以行为单位)?如果没有太大,您可以将内容放入列表并使用它们。
  • 你能举一个预期输出的例子吗?

标签: python bash csv awk


【解决方案1】:

更新答案

根据您的 cmets,我尝试重新设计 awk 以满足您的新需求。我可能会像这样对它们进行编码:

#!/bin/bash

# Do enzymatic/biochemical first

for f in *.csv; do
   awk -F, -v IGNORECASE=1 'NR>1 && ($18 ~ "enzymatic" || $18 ~ "biochemical") && $12<=10 {print $12,FILENAME}' "$f"
done | sort -n | tail -3

# Now do cell types

for f in *.csv; do
   awk -F, -v IGNORECASE=1 'NR>1 && $18 ~ "cell" && $12<=10 {print $12,FILENAME}' "$f"
done | sort -n | tail -3

但是,我认为以下可能更有效,更容易

egrep -Hi "enzyme|biochemical" *.csv | awk -F, '$12<=10{split($1,a,":");filename=a[1];print filename,$12}' | sort -n | tail -3

grep -Hi "cell" *.csv | awk -F, '$12<=10{split($1,a,":");filename=a[1];print filename,$12}' | sort -n | tail -3

原答案

我想这就是你的意思!

#!/bin/bash
for f in *.csv; do
   res=$(awk -F',' '
          BEGIN{IGNORECASE=1;field18ok=0} 
          $18 ~ "enzymatic" || $18 ~ "biochemical" || $18 ~ "cell" {field18ok=1}
          NR>1{if(!col4[$4]++)u++}
          END{print field18ok * u}' "$f")
   echo $res:$f
done | sort -n

它循环遍历所有.csv 文件,并一次将它们传递到awk

如果任何行在字段 18 中有您的 3 个关键字(大写或小写)之一,它会设置一个标志,表示字段 18 正常,并且是您正在查找的关键字之一。如果字段 18 不是您要查找的字段之一,则变量 fiedl18ok 将保持为零,并使最后打印的 answer 等于零。

下一部分,以NR&gt;1 开头,仅适用于行号大于1 的行,因此它基本上忽略了输入文件的标题行。然后它通过记住它在名为col4[] 的数组中已经在第 4 列中看到的所有值来对第 4 列中的唯一值求和。所以,我第一次向这个数组添加 1 时,我增加了 u(我在字段 4 中看到的唯一事物的数量。

最后,(END{}) 它将 field18ok 乘以第 4 列中唯一化合物的数量。因此,如果 field18 不是您想要的,答案将为零,而如果字段 18 是其中之一您要查找的值,它将是字段 4 中唯一值的数量。

然后对输出进行数字排序,以便您轻松选择最高值。

【讨论】:

  • 经过一些小修改后,完美运行!谢谢!
  • 您能解释一下这些是什么意思吗? "field18ok", NR>1{if(!col4[$4]++)u++} END{print field18ok * u}' "$f") echo $res:$f
  • 我扩展了描述以尝试解释代码在哪些方面做得更好。
  • 嗨,马克,在重新审视你的答案后,我不得不说这是一个非常优雅的答案。
  • 很高兴!很高兴为您服务。
【解决方案2】:

此代码读取所有文件数据,然后获取它的第 18 位(索引 17,因为从零开始)并添加到带有文件名键的字典,如果匹配值条件。
我使用了一个集合,因为这个结构不存储重复值。
最后,您只需检查所有集合值即可知道哪个具有最大唯一值

import csv
files        = ['Test_95_target_1334_assay_Detail3.csv','Test_95_target_1338_assay_Detail3.csv', 'Test_95_target_2888_assay_Detail3.csv']
pos_to_check = 17 #zero based index
pos_compound = 3
values_to_check = ["enzymatic", "biochemical" , "cell"]
result = dict([(file,set([])) for file in files ]) #file : set of compounds

for file in files:   
    with open(file, 'r') as csvfile:
        csvreader = csv.reader(csvfile)
        for row in csvreader:   
            if row[pos_to_check].lower() in values_to_check:
                result[file].add(row[pos_compound])

#get key which has more elements
max(result.iterkeys(), key=(lambda key: len(result[key])))

【讨论】:

    猜你喜欢
    • 2021-11-28
    • 2018-02-25
    • 2022-10-14
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多