我需要对一个非常大的数据集(1000 行和 700000 列)的列进行排序。例如,我的列随机排列,如:col1 col4 col3 col2,我需要对其进行排序。
我一直在尝试一些命令,但没有成功。
例子:
ID M2 M5 M8 M1 M3 M9 .....M7000000
Animal1 1 0 2 1 0 2 .....1
Animal2 0 1 2 0 1 1 .....0
Animal3 2 1 0 1 2 1 .....0
.
.
.
.
Animaln
在这个例子中,点意味着我有很多列和线。同样,我需要对列进行排序,如下所示:
ID M1 M2 M3 M4 M5 M6 .....M7000000
Animal1 1 0 2 1 0 2 .....1
Animal2 0 1 2 0 1 1 .....0
Animal3 2 1 0 1 2 1 .....0
.
.
.
.
Animaln
谢谢
答案1
与GNUdatamash
和 GNU sort
:
datamash transpose -t ' ' -H <file_in.csv | sort -V | datamash transpose -t ' ' -H >file_out.csv
这对于“相当小的”数据来说效果很好。它可能适用于您的文件,也可能不适用于您的文件。
编辑:以下没有换位的解决方案应该不会占用太多资源。
答案2
perl -pale '
$. == 1 and
@I = map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [ $F[$_] =~ /^M(\d+)$/, $_ ] } 1..$#F;
$_ = "@F[0, @I]";
' yourlargefile
- 对于第一行,我们
M
使用众所周知的Schwartzian maneuver
.这为我们提供了重新排序的索引,以便列按数字排序顺序出现(M1,M2,M3,...) - 剩下的就是使用这些索引来
@I
重新排列@F
元素。 - 以双引号形式分配数组会将其转换为元素以空格分隔的字符串。
-p
Perl 的选项允许自动打印$_
内容,-l
应添加newline
.
答案3
使用 perl 模块 Sort::Naturally
输入数据
ID M2 M5 M8 M1 M3 M9 M700000
A1 m1,2 m1,5 m1,8 m1,1 m1,3 m1,9 m1,7000000
A2 m2,2 m2,5 m2,8 m2,1 m2,3 m2,9 m2,7000000
A3 m3,2 m3,5 m3,8 m3,1 m3,3 m3,9 m3,7000000
A1000 m1000,2 m1000,5 m1000,8 m1000,1 m1000,3 m1000,9 m1000,7000000
perl -MSort::Naturally -lane '
if ($. == 1) {
@indices = (0, map { $_->[0] }
sort { ncmp($a->[1], $b->[1]) }
map { [$_, $F[$_]] }
1..$#F
);
$, = " ";
}
print @F[@indices]
' test.data
输出
ID M1 M2 M3 M5 M8 M9 M700000
A1 m1,1 m1,2 m1,3 m1,5 m1,8 m1,9 m1,7000000
A2 m2,1 m2,2 m2,3 m2,5 m2,8 m2,9 m2,7000000
A3 m3,1 m3,2 m3,3 m3,5 m3,8 m3,9 m3,7000000
A1000 m1000,1 m1000,2 m1000,3 m1000,5 m1000,8 m1000,9 m1000,7000000
答案4
如果你有 GNU awk
,你可以尝试这个:
NR == 1 {
for (i = 2; i <= NF; i++) {
columns[substr($i, 2)] = i;
}
count = asorti(columns, sorted, "@ind_num_asc");
printf("%s", $1);
for (i = 1; i <= count; i++) {
printf(" M%s", sorted[i]);
indx[i] = columns[sorted[i]];
}
print "";
next;
}
{
printf("%s", $1);
for (i = 1; i <= count; i++) {
printf(" %s", $(indx[i]));
}
print "";
}