首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据列中元素的频率选择行

如何根据列中元素的频率选择行
EN

Unix & Linux用户
提问于 2023-02-01 12:18:41
回答 1查看 143关注 0票数 4

如您所见,我有一个文件,它是由制表符分隔的数据,大约4,000行,10列。

文件的第二列记录不同的组织。

代码语言:javascript
复制
samples tissue_s tissue_e tissue_d tissue_category tissue_visa sex study tissue_f age
samples1  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples2  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples3  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples4  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples5  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples6  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples7  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples8  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples9  stomach CNS      ear       CNS            CNS        male  1   ear 365
...
...

我希望能把所有出现过十次以上的组织信息打印出来。

但是我认为这样做和生成中间文件是效率低下的。有没有一种更简洁、更有效的方法?

代码语言:javascript
复制
cat file | awk '{print $2}' | awk '{a[$0]++}END{for(i in a){if(a[i] > 10){print i}}}' > tmp.txt
grep -wFf tmp.txt file.txt > resule.txt
EN

回答 1

Unix & Linux用户

发布于 2023-02-03 22:00:04

使用Raku (以前称为Perl_6)

代码语言:javascript
复制
~$ raku -e 'my %h; do for lines.skip() {%h.push: .words.[1] => .words}; \
            for %h.kv -> $k,@v {(put $k; .put for @v) if @v.elems > 4};'  file

您可能有兴趣尝试一种Perl-家族语言,即Raku。一个优点是对Unicode内置的高级支持,您应该使用不同的语言排序规则与同事交换数据。

上面声明了一个%h散列,并将自动块lines (skipping标头行)编辑到它上,.words.[1] (第二列)作为键,.words (所有列)作为值。由于%h散列中不存在重复的键,所以在第二列中的每个单独的组织下都会添加行。一旦处理完所有行,哈希将被%h.kv键值处理为标量$k键和数组中的@a值。只打印@v.elems > 4 (即OP的示例输入超过4行)。

样本输入:

代码语言:javascript
复制
samples tissue_s tissue_e tissue_d tissue_category tissue_visa sex study tissue_f age
samples1  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples2  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples3  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples4  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples5  ear     CNS      ear       CNS            CNS        male  1   ear 365
samples6  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples7  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples8  stomach CNS      ear       CNS            CNS        male  1   ear 365
samples9  stomach CNS      ear       CNS            CNS        male  1   ear 365

示例输出(来自上述代码):

代码语言:javascript
复制
ear
samples1 ear CNS ear CNS CNS male 1 ear 365
samples2 ear CNS ear CNS CNS male 1 ear 365
samples3 ear CNS ear CNS CNS male 1 ear 365
samples4 ear CNS ear CNS CNS male 1 ear 365
samples5 ear CNS ear CNS CNS male 1 ear 365

调整输出以满足您的需要是相当容易的。如果您不想要一个单独的“组织”头线,请放弃对put $k;的调用。此外,将@a行输出更改为.join("\t").put for @v,以重新构成\t制表符分隔行.

注意,上面的答案假设每个列条目都没有空白,因为.words在空格上拆分(\t与否)。如果不能保证每个列条目都是一个空格分隔的元素,那么请使用.split("\t")。把它们放在一起(给出与上面相同的输出,但现在用制表符分隔):

代码语言:javascript
复制
~$ raku -e 'my \%h; do for lines.skip() {\%h.push: .split("\t").[1] => .split("\t")}; \
            for \%h.kv -> $k,@v {($k.put; .join("\t").put for @v) if @v.elems > 4};'  file

https://docs.raku.org https://raku.org

票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/733937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档