使用 bash 脚本或 python 操作 csv 文件,将某些列转换为行

使用 bash 脚本或 python 操作 csv 文件,将某些列转换为行

我有一个包含 6 列的 csv 文件。我想使用 Python 或 Bash 编写一个脚本,以便我可以生成一个新文件,可能是 txt 文件,其中每行的前三列保持不变(即第 1、2 和 3 列保持在同一行),但接下来的三列(即第 4、5、6 列)插入到新行中,就在上一行的下方。

我的示例文件如下所示:

Column1   Column2    Column3     Column4    Column5      Column6
chr16    2697996    2697997     chr16      2086192      2086193
chr5    112801382   112801383   chr5       138445682    138445683
chr15   26869333    26869334    chr8       119416385    119416386

我的最终文件应如下所示:

Column1  Column2     Column3
chr16   2697996     2697997
chr16   2086192     2086193
chr5    112801382   112801383
chr5    138445682   138445683
chr15   26869333    26869334
chr8    119416385   119416386

答案1

这里有一种awk方法:

$ awk 'NR>1{for(i=1;i<=NF;i++){ if((i%4)==0) printf "\n"; printf "%s%s",$i,FS;}printf "\n"} END{printf "\n"}' input.csv
chr16 2697996 2697997 
chr16 2086192 2086193 
chr5 112801382 112801383 
chr5 138445682 138445683 
chr15 26869333 26869334 
chr8 119416385 119416386

假设文件中存在“列”,则在没有它们的情况下处理文件会更容易,因此是NR>1部分。之后是一个简单的 for 循环,当列号(部分)的整数除以 4 没有余数时,它会插入一个换行符(i%4) == 0。这是一个非常常见的技巧,用于处理短计数器或需要在特定间隔发生的数据。换行符是必要的,因为我们printf直接通过纯字符串而不是整行打印数据。


由于您请求了 python,这里也有一个 python 脚本:

#!/usr/bin/env python3
import sys

with open(sys.argv[1]) as fd:
    for index,line in enumerate(fd):

        items=line.strip().split()
        if index == 0:
            print(" ".join(items[:len(items)//2]))
            continue

        left = items[:len(items)//2]
        right = items[len(items)//2:]
        print( " ".join(left) )
        print( " ".join(right) )

工作原理如下:

$ ./break_columns.py ./input.csv 
Column1 Column2 Column3
chr16 2697996 2697997
chr16 2086192 2086193
chr5 112801382 112801383
chr5 138445682 138445683
chr15 26869333 26869334
chr8 119416385 119416386

答案2

您可以使用 Miller (https://github.com/johnkerl/miller) 和一个 bash 脚本。从输入开始

Column1   Column2    Column3     Column4    Column5      Column6
chr16    2697996    2697997     chr16      2086192      2086193
chr5    112801382   112801383   chr5       138445682    138445683
chr15   26869333    26869334    chr8       119416385    119416386

并运行

<input tail -n +2 | mlr --nidx --ifs ' ' --repifs cut -f 1,2,3 >out_01
<input tail -n +2 | mlr --nidx --ifs ' ' --repifs cut -f 4,5,6 >out_02

mlr --nidx --ifs ' ' --repifs cat out_01 out_02 >out

mlr -I --n2c --fs ' ' cat then label Column1,Column2,Column3 out

你将会拥有

Column1 Column2 Column3
chr16 2697996 2697997
chr5 112801382 112801383
chr15 26869333 26869334
chr16 2086192 2086193
chr5 138445682 138445683
chr8 119416385 119416386

如果你想要漂亮的打印输出,请将最后一个命令更改为mlr -I --n2p --fs ' ' cat then label Column1,Column2,Column3 out

Column1 Column2   Column3
chr16   2697996   2697997
chr5    112801382 112801383
chr15   26869333  26869334
chr16   2086192   2086193
chr5    138445682 138445683
chr8    119416385 119416386

相关内容