从纯文本文件中细化和构建 csv 文件

Posted

技术标签:

【中文标题】从纯文本文件中细化和构建 csv 文件【英文标题】:Elaborate and structure a csv file from a plain text file 【发布时间】:2022-01-01 03:37:40 【问题描述】:

不知道有没有办法转换如下图所示的纯文件

target: locus9_window12
length: 120
miRNA : hsa-miR-4458
length: 19
mfe: -23.7 kcal/mol
p-value: 0.033901
target: locus104_window172
length: 120
miRNA : hsa-let-7b-5p
length: 22
mfe: -26.2 kcal/mol
p-value: 0.015466
target: locus119_window193
length: 120
miRNA : hsa-let-7b-5p
length: 22
mfe: -32.8 kcal/mol
p-value: 0.00028

转为逗号分隔的csv类型格式

target                length   miRNA           length   mfe      p-value
locus9_window12       120      hsa-miR-4458     19      -23.7    0.033901 
locus104_window172    120      hsa-let-7b-5p    22      -26.2    0.015466
locus119_window193    120      hsa-let-7b-5p    22      -32.8    0.00028

如果可以将纯文本文件转换为逗号分隔的 csv 文件,我将不胜感激任何支持和贡献

【问题讨论】:

字段的顺序是否始终相同?一个都没有? 没错,它们总是按照明文所示的顺序进行 【参考方案1】:

这是一个使用正则表达式和 pandas 方法的潜在解决方案。我将第二个 length 数据字段重写为 miRNA_length(假设它是 miRNA 的长度)以避免重复的列名。

with open('filename.txt') as f:
    t = f.read()

import re

df = (pd.DataFrame(re.findall(r'([^\s:]+)\s*: (\S*)', t), columns=['col', 'value'])
        # rename the length field that follows miRNA
        .assign(col=lambda d: d['col'].mask(d['col'].shift().eq('miRNA'), 'miRNA_length'))
        # group the data by row
        .assign(index=lambda d: d.groupby('col').cumcount())
        # reshape to wide format
        .pivot(index='index', columns='col', values='value')
        .rename_axis(index=None, columns=None)
        # convert the data types (e.g numeric)
        .convert_dtypes()
      )

输出:

  length    mfe          miRNA miRNA_length   p-value              target
0    120  -23.7   hsa-miR-4458           19  0.033901     locus9_window12
1    120  -26.2  hsa-let-7b-5p           22  0.015466  locus104_window172
2    120  -32.8  hsa-let-7b-5p           22   0.00028  locus119_window193

如果不是文件则输入文本:

t = '''target: locus9_window12
length: 120
miRNA : hsa-miR-4458
length: 19
mfe: -23.7 kcal/mol
p-value: 0.033901
target: locus104_window172
length: 120
miRNA : hsa-let-7b-5p
length: 22
mfe: -26.2 kcal/mol
p-value: 0.015466
target: locus119_window193
length: 120
miRNA : hsa-let-7b-5p
length: 22
mfe: -32.8 kcal/mol
p-value: 0.00028
'''

另存为 CSV:

df.to_csv('out.csv') # check the doc for more options

【讨论】:

嗨。有没有办法添加另一列?如何添加名为“位置”的列?【参考方案2】:

miller 非常适合这种文件格式。 输入文件需要稍微调整一下,在每条记录之间添加一个空行,并删除冒号

awk -F: 'NR > 1 && $1 == "target" print ""; sub(/:/,""); print' file \
| mlr --ixtab --ocsv cat

输出

target,length,miRNA,mfe,p-value
locus9_window12,19,hsa-miR-4458,-23.7 kcal/mol,0.033901
locus104_window172,22,hsa-let-7b-5p,-26.2 kcal/mol,0.015466
locus119_window193,22,hsa-let-7b-5p,-32.8 kcal/mol,0.00028

【讨论】:

【参考方案3】:

假设您的文本文件中没有逗号,并且您要打印的字段中没有空格,GNU awk 可以提供帮助:

# foo.awk
BEGIN 
  print "length,mfe,miRNA,miRNA_length,p-value,target"


  fields[NR%6] = $NF

NR%6 == 0 
  for(i=1; i<=6; i++) printf("%s%c", fields[i%6], i==6 ? "\n" : OFS)

然后:

awk -v OFS=, -f foo.awk foo.txt
length,mfe,miRNA,miRNA_length,p-value,target
locus9_window12,120,hsa-miR-4458,19,kcal/mol,0.033901
locus104_window172,120,hsa-let-7b-5p,22,kcal/mol,0.015466
locus119_window193,120,hsa-let-7b-5p,22,kcal/mol,0.00028

说明:我们在索引“行号模 6”(NR%6) 处使用每行的最后一个字段 ($NF) 填充 fields 数组。请注意,行号从 1 开始,因此每组 6 中的最后一个在数组中索引为 0,而不是 6。如果当前记录号是 6 的倍数,我们将打印 fields 数组的内容。输出字段分隔符设置为逗号 (-v OFS=,)。

【讨论】:

以上是关于从纯文本文件中细化和构建 csv 文件的主要内容,如果未能解决你的问题,请参考以下文章

将文本文件中的数据导入 pandas 数据框

Python:从 CSV 文件中的列创建多个文本文件

在 Python 中读取用于决策树学习的 CSV 文本文件

Azure API App,在哪里存储纯文本文件?

csv文件转换成excel的方法

csv 文件中单元格内的字段和文本分隔符