3. Krona 输入数据格式:标准层级格式

好,咱们直接切入正题。Krona 这个工具,说白了就是个「看图工具」。你给它什么数据,它就画什么图。如果数据格式不对,它要么报错,要么画出一堆乱糟糟的圈——嗯,我见过不少初学者拿 Excel 直接复制粘贴过来的数据,结果 Krona 显示出一堆「Unclassified」,那场面别提多尴尬了。

所以,搞清楚 Krona 的输入格式,是你能不能做出漂亮交互式图表的第一道门槛。我个人觉得,这一步搞明白了,后面基本都是水到渠成的事。

3.1 核心规则:一行一个分类路径

Krona 的标准输入格式,其实特别简单:

  • 每行代表一个分类路径,从最上级到最下级,用 Tab 分隔。
  • 路径后面跟着一个数字,代表这个路径的读长计数(count)或者相对丰度(abundance)。
  • 分类节点之间必须是 Tab,不是空格,不是逗号,更不是分号。这个坑,我踩过。

来看一个最基础的对的比例子:

Bacteria	Proteobacteria	Escherichia	E. coli	1000
Bacteria	Firmicutes	Bacillus	B. subtilis	500
Eukaryota	Fungi	Saccharomyces	S. cerevisiae	200

你看,每一行定义了一条完整的分类路径。Krona 拿到这些数据后,会沿着路径一层层画圈,最内层是「Bacteria」和「Eukaryota」,往外展开。最后一列的 1000、500、200 就是每个最小分类单元的丰度。

核心规则速记:

  • Tab 分隔,层级从大到小
  • 最后一列必须是数字(整数或浮点)
  • 不支持空字段,比如「Bacteria E. coli」这种会出问题
  • 路径深度不限,但太深了(比如超过30层)图标会乱

3.2 两种输入方式:计数 vs 相对丰度

Krona 支持两种数值字段,你选哪种都行,但必须统一。我在项目中遇到过有人同一份文件里混用,结果 Krona 把几百的相对丰度和几万的 counts 画在一起,最外面一圈直接看不见。

类型 说明 示例 注意
Count(计数) 每个分类路径的原始读长数
Bacteria	Proteo	1000
整数或小数都行,Krona 会自动归一化
Abundance(相对丰度) 百分比或归一化后的值
Bacteria	Proteo	0.35
同一文件内所有丰度值和应为 1.0(或 100)

我个人习惯用 counts 原始值。为什么?因为后期如果你想做差异分析或者合并样本,原始 counts 比归一化后的丰度灵活太多了。不过你要用丰度也没问题,Krona 两种都吃得下。

3.3 如何处理多层级:从粗到细的排列

你想想看,一个真实的微生物样本,可能有几十个门、几百个属、上千个种。你怎么组织文件?

答案是:每一行独立写完整的路径。不要想着只写差异部分,Krona 没有「继承」的概念。

举个例子,如果你有三个样本,一个属于 E. coli,一个属于 S. aureus,一个属于 B. subtilis,你不能这样写:

Bacteria	Proteobacteria	E. coli	300
Bacteria	Firmicutes	S. aureus	200
B. subtilis	150

最后一行缺了「Bacteria」和「Firmicutes」,Krona 会直接把「B. subtilis」挂在根节点下面,变成一个新的门级别分类。数据就乱套了。

正确写法是:

Bacteria	Proteobacteria	E. coli	300
Bacteria	Firmicutes	S. aureus	200
Bacteria	Firmicutes	B. subtilis	150

我曾经的踩坑回忆: 有一次我用脚本批量处理 NCBI 的分类数据,结果脚本里有个 bug,把中间层级漏了一级。生成的表格看起来数据全的,但 Krona 画出来多出了十几个「Unclassified」节点。我排查了半天才发现,是某行的路径里少了一个 Tab。嗯,从那以后我写了个检查脚本,专门扫描路径的深度是否一致。

3.4 层级名称中的空格和特殊字符

分类名称里常常有空格,比如「Escherichia coli」「Candidatus Saccharibacteria」。Krona 的字段是靠 Tab 区分的,所以名称本身可以包含空格,没问题。

但有些特殊字符可能会出幺蛾子:

  • Tab 字符绝对不能出现在分类名称内部。如果你遇到名称里带 Tab 的情况——说实话我从来没遇见过——你需要先清洗数据。
  • 引号和括号:Krona 对单引号、双引号、括号都能正常处理。但如果你用「>」「<」或者「&」这些 HTML 敏感字符,Krona 在生成 HTML 界面时可能会解析异常。建议提前替换成_或-。
  • 换行符:每个分类路径必须在一行内写完整,不能折行。我记得有一次我用 Windows 的 Notepad 编辑文件,不小心按了回车,Krona 直接报了个「Unterminated path」错误。

一个实用的小窍门: 写一段 Python 脚本来验证你的输入文件。检测内容:1)每行的 Tab 数量是否一致;2)最后一列是否为数字;3)路径深度是否都相同。这个脚本我至今还在用,每次跑新数据前都会过一遍,省了太多排查时间。

def validate_krona_input(filepath):
    with open(filepath, 'r') as f:
        lines = f.readlines()
    tab_counts = [line.count('\t') for line in lines if line.strip()]
    if len(set(tab_counts)) > 1:
        print(f"Warning: Inconsistent tab counts: {set(tab_counts)}")
        return False
    for line in lines:
        parts = line.strip().split('\t')
        if not parts[-1].replace('.', '', 1).isdigit():
            print(f"Error: Last column not numeric: {line}")
            return False
    print("Validation passed")
    return True

3.5 支持多样本合并:共享分类路径

Krona 还有一个硬核功能:一个文件可以包含多个样本的数据。怎么做?在分类路径后面加多列数值,每列代表一个样本。

比如:

Bacteria	Proteobacteria	E. coli	1200	800	300
Bacteria	Firmicutes	B. subtilis	500	200	450
Eukaryota	Fungi	S. cerevisiae	100	0	50

这里第三列是样本1的 counts,第四列是样本2的 counts,第五列是样本3的。Krona 在可视化时,会把每个样本当作独立的「数据集」,你可以在交互界面里切换查看。

这个功能我特别喜欢,用来做不同时间点或不同处理组的比较图特别方便。不过要注意:所有样本的列数必须一致。如果某个分类在一个样本里是 0,你不能空着,必须写 0。

3.6 SVG 图:输入数据到 Krona 可视化的流程

下面这张图展示了从原始数据到 Krona 交互图的完整流程,重点突出了输入数据格式的位置和作用。

Krona 输入数据处理流 原始测序数据 分类工具(Kraken2等) 标准层级格式 (Tab分隔,路径+计数/丰度) Krona 交互图 输入文件核心规则: · 每行一条完整分类路径 · 字段之间必须是 Tab · 最后一列为数值(计数或丰度) 推荐检查点: · 所有行 Tab 数量一致 · 路径深度对应正确的分类层级 · 多样本时各列对应关系正确

3.7 实际案例:从 Kraken2 报告到 Krona 输入

最常用的情况是,你先用 Kraken2 拿到分类结果,然后转换成 Krona 格式。Kraken2 的输出通常是这样的:

25.36	1234	1000	B	Bacteria
12.50	567	500	P	Proteobacteria
8.20	345	300	G	Escherichia
5.10	200	150	S	Escherichia coli

你需要把这堆数据转成 Krona 能吃的格式。说白了,就是把每一行的分类路径拼起来,带上 counts 列。下面是我常用的 awk 命令:

awk -F'\t' '{
  # 提取分类路径(第6列往后)和counts(第3列)
  path = $6
  for(i=7;i<=NF;i++) path = path "\t" $i
  print path "\t" $3
}' kraken2_report.txt > krona_input.txt

跑完以后,你看看结果是不是这样的:

Bacteria	Proteobacteria	Escherichia	Escherichia coli	1234
Bacteria	Proteobacteria	Escherichia	Escherichia coli	567
Bacteria	Proteobacteria	Escherichia	Escherichia coli	345

哦等等,上面这个输出有问题——同一分类路径出现了多次。这是因为 Kraken2 报告里每个层级都有独立一行。你需要把相同路径的 counts 合并起来。嗯,这里要注意。

修正后的做法:用 sort 加 awk 去重求和。

awk -F'\t' '{
  path = $6
  for(i=7;i<=NF;i++) path = path "\t" $i
  counts[path] += $3
} END {
  for(p in counts) print p "\t" counts[p]
}' kraken2_report.txt | sort > krona_input.txt

这样出来的文件就干净了,每个分类路径只出现一次,counts 是汇总后的值。

关于文件编码的提醒: 我遇到过最恶心的情况是,从 Windows 环境拷过来的文件,行尾是 \r\n(CRLF),Krona 在 Linux 下解析时,最后一个字段会带个 \r,导致数字解析失败。解决办法:跑之前先做一次 dos2unix 或者用 sed 's/\r//' 清洗一下。

3.8 小结:输入格式就是 Krona 的「语言」

Krona 的输入格式,说白了就两样东西:Tab 分隔的分类路径 + 末位的数值。简单归简单,细节里全是坑。

我个人建议,每次生成输入文件后,先跑我之前给的那个验证脚本,检查一下 Tab 数量和路径深度。等数据确认无误了,再用 ktImportText 生成可视化报告。熟练了之后,从原始数据到 Krona 图,整个过程不会超过五分钟。

嗯,格式讲完了。下一块内容我们聊聊怎么用 Krona 自带的 ktImportText 命令来生成真正的 HTML 报告——那个才是你交付给同事或客户的最终产出物。