在jq中将逗号分隔文件转换为嵌套对象json

在jq中将逗号分隔文件转换为嵌套对象json,json,bioinformatics,hierarchical-data,jq,Json,Bioinformatics,Hierarchical Data,Jq,我有一个CSV文件,我想用jq解析并获得一个嵌套的JSON。我最近开始使用JQ,我真的很喜欢这个工具。我了解基本功能,但解析csv文件似乎有点困难,尤其是打印嵌套对象 样本输入 基因,外显子,总,外显子碱基,总碱基,外显子碱基分数 PIK3CA,PIK3CA_外显子10;chr1;1000;1500,PIK3CA_外显子13;chr1;1000;1500,PIK3CA_外显子14;chr1;1000;1500,1927879,12993042,0.15 NRAS,NRAS_外显子4;chr1;1

我有一个CSV文件,我想用jq解析并获得一个嵌套的JSON。我最近开始使用JQ,我真的很喜欢这个工具。我了解基本功能,但解析csv文件似乎有点困难,尤其是打印嵌套对象

样本输入 基因,外显子,总,外显子碱基,总碱基,外显子碱基分数 PIK3CA,PIK3CA_外显子10;chr1;1000;1500,PIK3CA_外显子13;chr1;1000;1500,PIK3CA_外显子14;chr1;1000;1500,1927879,12993042,0.15 NRAS,NRAS_外显子4;chr1;1000;1500,NRAS_Amp_369;chr1;1000;1500,NRAS_Amp_371;chr1;1000;1500,NRAS_Amp_374;chr1;1000;1500,NRAS_Amp_379;chr1;1000;15008841118062107,0.11

标题和输入数据说明 第一列将始终具有一个值。第二列可以有多个外显子(1个或更多)。您可以看到,它在第二行有3个值,在第三行有5个值。外显子碱基将始终是最后一列中的第二列,总碱基将是最后一列,但外显子碱基的一部分将是最后一列

注 我添加标题是为了解释,可以删除或修改标题以进行处理

预期产量 提前谢谢你的帮助

PS:-我需要添加更多信息,我必须编辑外显子字段,并为每个外显子添加“染色体”、“开始”和“结束”。在这里,我给出了相同的起点和终点,但在实际情况中,每个外显子的起点和终点都不同。你能帮我做这个吗。 此外,这些外显子的输入也可以用任何其他字符来分隔。现在我用“;”

来分隔它。这里有一个解决方案:(a)根据标题的注释,假设没有标题行(但请参见下文);(b) 不“咕哝”文件(即。, 不将整个文件读入内存);和(c)假设jq版本具有
输入
。(如果jq没有
输入
,则很容易相应地修改以下内容。)

jq的适当调用应遵循以下原则:

jq -n -R -f program.jq input.txt
这将生成所需的JSON

(R代表“原始输入”。)

如果输入文件确实有一个标题行,只要您删除“-n”命令行选项,上述解决方案仍然有效


请注意,尽管输入文件有逗号分隔的值,但它实际上不是一个CSV文件。

以下是一个使用函数解析和组装输出的解决方案:

def parse:
  [
      inputs                     # read lines
    | split(",")                 # split into columns
    | select(length>0)           # eliminate blanks
    | .[:1] + [.[1:-3]] + .[-3:] # normalize columns
  ]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v):    {metric:n, value:v,          type:"set"};
def region:
  set(.[0]; [
      set("Exons"; .[1]),
      simple("Fraction of bases"; .[2]),
      simple("Total_bases"; .[3])
    ]
  )
;
{
   "Exome regions": parse | map(region)
}
示例运行(假设筛选器位于
filter.jq
中,数据位于
data.json


以下是修订后问题的解决方案:

def parse:
  [
      inputs                     # read lines
    | split(",")                 # split into columns
    | select(length>0)           # eliminate blanks
    | .[:1] + [.[1:-3]] + .[-3:] # normalize columns
  ]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v):    {metric:n, value:v,          type:"set"};
def exons(v):    [ v[] | split(";") | .[0], {"chromosome":.[1], "start":.[2], "end":.[3]} ];
def region:
  set(.[0]; [
      set("Exons"; exons(.[1])),
      simple("Fraction of bases"; .[2]),
      simple("Total_bases"; .[3])
    ]
  )
;

{ "Exome regions": parse | map(region) }

非常感谢!这个代码就像一个符咒。是的,这更像是一个带有逗号分隔值的文件,而不是一个CSV。如果可以避免使用-s选项(如此处所示),则如果输入文件有多行,则不建议使用-s选项。如果您的jq没有
输入
,只需使用
减少
。同意。我已经用
-n
-parse
中的
-s
-inputs
替换了
-s
split(“\n”)[/code>的使用。我已经为修改后的问题添加了一个解决方案。这非常棒,效果很好。是否有任何指针可以了解更多关于jq复杂函数的信息。与之配套的视频也很好。和有很多好的信息和学习方面的帮助,特别是。我还需要一个帮助,是否有可能拆分外显子并创建键值对。PIK3CA,PIK3CA_外显子10;chr;2.100,PIK3CA_外显子13;chr;100;200,PIK3CA_外显子14;chr;2000;10000192787912993042,0.15个键为染色体,起始和结束,值位于外显子中,用“;”分隔
def parse:
  [
      inputs                     # read lines
    | split(",")                 # split into columns
    | select(length>0)           # eliminate blanks
    | .[:1] + [.[1:-3]] + .[-3:] # normalize columns
  ]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v):    {metric:n, value:v,          type:"set"};
def region:
  set(.[0]; [
      set("Exons"; .[1]),
      simple("Fraction of bases"; .[2]),
      simple("Total_bases"; .[3])
    ]
  )
;
{
   "Exome regions": parse | map(region)
}
$ jq -M -Rnr -f filter.jq data.json
{
  "Exome regions": [
    {
      "metric": "PIK3CA",
      "value": [
        {
          "metric": "Exons",
          "value": [
            "PIK3CA_Exon10",
            "PIK3CA_Exon13",
            "PIK3CA_Exon14"
          ],
          "type": "set"
        },
        {
          "metric": "Fraction of bases",
          "value": 1927879,
          "type": "simple"
        },
        {
          "metric": "Total_bases",
          "value": 12993042,
          "type": "simple"
        }
      ],
      "type": "set"
    },
    {
      "metric": "NRAS",
      "value": [
        {
          "metric": "Exons",
          "value": [
            "NRAS_Exon4",
            "NRAS_Amp_369",
            "NRAS_Amp_371",
            "NRAS_Amp_374",
            "NRAS_Amp_379"
          ],
          "type": "set"
        },
        {
          "metric": "Fraction of bases",
          "value": 884111,
          "type": "simple"
        },
        {
          "metric": "Total_bases",
          "value": 8062107,
          "type": "simple"
        }
      ],
      "type": "set"
    }
  ]
}
def parse:
  [
      inputs                     # read lines
    | split(",")                 # split into columns
    | select(length>0)           # eliminate blanks
    | .[:1] + [.[1:-3]] + .[-3:] # normalize columns
  ]
;
def simple(n;v): {metric:n, value:v|tonumber, type:"simple"};
def set(n;v):    {metric:n, value:v,          type:"set"};
def exons(v):    [ v[] | split(";") | .[0], {"chromosome":.[1], "start":.[2], "end":.[3]} ];
def region:
  set(.[0]; [
      set("Exons"; exons(.[1])),
      simple("Fraction of bases"; .[2]),
      simple("Total_bases"; .[3])
    ]
  )
;

{ "Exome regions": parse | map(region) }