从纯文本文件中细化和构建 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 文件的主要内容,如果未能解决你的问题,请参考以下文章