在循环中重新排列列数据



我有一个data.csv文件,它包含如下所示的连接数据。>是连接文件的分隔符。

>
1.094   1.128   1.439
3.064   3.227   3.371
>
5.131   5.463   5.584
3.65    3.947   4.135
>
1.895   1.954   2.492
5.307   5.589   5.839

我想重新排列列数据并排,最后想保存到新的文本文件如下所示。对于这个演示示例,我们可以创建三个文件。此外,额外的0和5应该作为额外的行追加。

cat file1.txt
1.094  5.131  1.895 0 5
3.064  3.65   5.307 0 5
cat file2.txt
1.128  5.463  1.954 0 5
3.227  3.947  5.589 0 5
cat file3.txt
1.439  5.584  2.492 0 5
3.371  4.135  5.839 0 5

My trial code

import pandas as pd
df = pd.read_csv('data.csv', sep='t')
for columns in df:
data=df.iloc[:,columns]
data.concat['data']
data.to_csv('file1.txt')

错误:ValueError:基于位置的索引只能有[integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike integer, boolean array]类型

我没有得到预期的输出。希望专家可以帮助我。谢谢。

假设:

  • 每个>分隔块有2行数据
  • 数据行可以包含可变数量的列(3在提供的示例输入中)
  • 所有数据行具有相同的列数(提供的样例输入中的3)
  • 输出文件名的形式为fileI.txt,其中I的范围从1到输入数据行的列数(提供的示例数据中的3)
  • OP的主机有足够的内存来保存整个输入文件(通过awk数组)

一个awk的想法:

awk '
/^>/   { next }
{ if (! colcnt) colcnt=NF                         # make note of number of columns; used to deep track of number of output files
for (i=1;i<=colcnt;i++)
row1[i]=row1[i] (row1[i] ? OFS : "") $i
getline
for (i=1;i<=colcnt;i++)
row2[i]=row2[i] (row2[i] ? OFS : "") $i
}
END    { for (i=1;i<=colcnt;i++) {
print row1[i],0,5 > "file" i ".txt"
print row2[i],0,5 > "file" i ".txt"
}
}
' data.csv

注意:OP的示例代码暗示tab (t)分隔输入,但OP的附加注释似乎表明数据是(可变)空格分隔的;如果/当OP提供对输入/输出分隔符

的更新要求时,可以更改输入/输出分隔符。由此产生:

$ head file*.txt
==> file1.txt <==
1.094 5.131 1.895 0 5
3.064 3.65 5.307 0 5
==> file2.txt <==
1.128 5.463 1.954 0 5
3.227 3.947 5.589 0 5
==> file3.txt <==
1.439 5.584 2.492 0 5
3.371 4.135 5.839 0 5

另一个使用jq的解决方案。
假设:Unix行结束,data.csv开始的行只包含">"并以空行结束。

for column in 1 2 3; do jq -Rsr --argjson column $column '
split(">n")[1:]
|map(  
split("n")[:-1]|map(split("t"))  
) as $arr
|[ 
[ $arr[][0][$column-1]],[$arr[][1][$column-1] ] 
|.+["0","5"] 
|join("t")  
]|join("n") 
' data.csv > file$column.txt; done

结果:

$ head file*.txt
==> file1.txt <==
1.094   5.131   1.895   0       5
3.064   3.65    5.307   0       5
==> file2.txt <==
1.128   5.463   1.954   0       5
3.227   3.947   5.589   0       5
==> file3.txt <==
1.439   5.584   2.492   0       5
3.371   4.135   5.839   0       5

在python中使用numpy。下面的代码应该工作,我认为,不管有多少列有在原始文件(3在您的例子)。它确实假设2行的块。下面的代码更新,以考虑到原始文件实际上没有被tabs分隔,如最初建议的

import pandas as pd
import numpy as np
fname = "data.txt" # file is apparently only separated with spaces, and then
# (one assumes) only for those lines that include data (not the lines with ">")
# some minor adjustments:
df = pd.read_csv(fname, header=None)
# get rid of rows with ">" separator
df = df[~df[0].str.contains('>')]
# now split all remaining rows
df = df[0].str.split(expand=True)
# change dtype (first col will be dtype "object" due to ">" separator)
df = df.astype(float)
col_len = len(df.columns)
# add some data
df2 = pd.DataFrame(np.array([[0]*(col_len)*2,[5]*(col_len)*2]).reshape(4,col_len))
# concat orig data + added data
df_col = pd.concat([df, df2], ignore_index=True)
# convert to numpy array, and reshape 
arr = df_col.to_numpy().reshape(int(df_col.shape[0]/2),2,col_len).T
# split up again
tup = np.split(arr,col_len)
# loop through tuple and write away the files
for idx, elem in enumerate(tup):
# numpy arr will be nested, so get elem[0]:
np.savetxt(f'file{idx+1}.txt', X=elem[0], fmt='%1.3f', delimiter='t')

最后一次循环print(elem[0])的结果:

[[1.094 5.131 1.895 0.    5.   ]
[3.064 3.65  5.307 0.    5.   ]]
[[1.128 5.463 1.954 0.    5.   ]
[3.227 3.947 5.589 0.    5.   ]]
[[1.439 5.584 2.492 0.    5.   ]
[3.371 4.135 5.839 0.    5.   ]]

最新更新