如何从列 #x 中提取唯一值及其对应的列 #y 值?

如何从列 #x 中提取唯一值及其对应的列 #y 值?

我有一个逗号',' FS 文件名,为 csv,有 n 列。我需要从中提取独特的价值colm.#1仅具有相应的值colm.#10。所以基本上第 10 列是日期,colm.#1尽管有其他列,但它始终是唯一的。

文件内容filename

colm.#1 colm.#2 colm.#3 colm.#4 colm.#5 colm.#6 colm.#7 colm.#8 colm.#9 colm.#10    colm.#11
    a   231 412 30.84873962 3   1   1   2013    5/28/2013   6/6/2006    299
    c   12  41  66.80690765 3   1   1   2014    5/25/2014   4/4/2004    351
    d   35  6   25.91622925 3   1   2   2013    6/27/2013   3/3/2003    303
    d   352 55  33.91288757 3   1   2   2014    6/26/2014   3/3/2003    355
    a   86  3   30.58783722 3   1   3   2013    7/24/2013   6/6/2006    307
    c   15  3242    26.6435585  3   1   3   2014    7/24/2014   4/4/2004    359
    e   67  1   22.95526123 3   1   4   2013    8/21/2013   5/5/2005    311
    a   464 64  4.804824352 3   1   4   2014    8/20/2014   6/6/2006    363
    b   66  42  29.42435265 3   1   5   2014    9/18/2014   7/7/2007    367
    m   24  2   66.10663319 3   1   6   2014    10/13/2014  9/9/2009    371

我尝试了以下命令,但它仅适用于colm.#1并且我不知道如何获取colm.#10.

cut -d',' -f1 filename |uniq

预期输出为:

a   6/6/2006
b   7/7/2007
c   4/4/2004
d   3/3/2003
e   5/5/2005
m   9/9/2009

答案1

awk -F, 'NR > 1 && ! seen[$1 FS $10]++ {print $1, $10}' filename | sort -k1,1

输出

a 6/6/2006
b 7/7/2007
c 4/4/2004
d 3/3/2003
e 5/5/2005
m 9/9/2009

答案2

awk '{if ( ! ( $1 in Peers)) { Peers[$1]=$1 " " $10; print Peers[$1]} }' YourFile

这将按顺序进行,如果您需要对结果进行排序,请在 shel (输入或输出)或(使用 GNU awk)中进行排序

awk '{if ( ! ( $1 in Peers)) Peers[$1]=$1 " " $10 } END{asort(Peers);for (Peer in Peers) print Peers[ Peer]}' YourFile

答案3

如果您想使用剪切打印多个字段:

cut -d (SELECT DELIMITER) -f 1,10

-f 1,10仅选择指定的字段。

如果您的目标是特定的线路,您可以这样做: grep -w a filename | cut -d (SELECT DELIMITER) -f 1,10

在上面的例子中,您正在寻找字母“a”的精确匹配。意思是,“apple”不会太多,但“a”却会。

答案4

使用(以前称为 Perl_6)

在 Raku 中,基于单个“列”对行进行“唯一化”的一般方法如下:

raku -e '.put for lines.unique: :as(*.words[9]);'

上面的代码打印与unique第 1 列(又名 )中找到的值相对应的整行:as(*.words[0])。因此,如果您只需要第 1 列和第 10 列,只需选择它们(零索引)words

raku -e '.words[0,9].put for lines.unique: :as(*.words[9]);'

words在同一个单行中调用两次可能效率低下,因此我们可以使用given主题化器抽象出该函数调用:

raku -e 'given lines.map(*.words) { .[0,9].put for .unique: :as(*.[9]) };' 

或者,仅使用for迭代器:

raku -e ' .[0,9].put for lines.map(*.words).unique( :as(*.[9]) ) ;' 

除了标题行之外,它几乎可以处理 simple-tsv 文件。如果您需要处理标头,put请先将其取出。由于lines是有状态的,它将恢复从标头后的第一个数据行读取:

~$ raku -e 'lines.head(1).words.[0,9].put; \
          .[0,9].put for lines.map(*.words).unique( :as(*.[9]) ) ;'  file

输入示例:

colm.#1 colm.#2 colm.#3 colm.#4 colm.#5 colm.#6 colm.#7 colm.#8 colm.#9 colm.#10    colm.#11
a   231 412 30.84873962 3   1   1   2013    5/28/2013   6/6/2006    299
c   12  41  66.80690765 3   1   1   2014    5/25/2014   4/4/2004    351
d   35  6   25.91622925 3   1   2   2013    6/27/2013   3/3/2003    303
d   352 55  33.91288757 3   1   2   2014    6/26/2014   3/3/2003    355
a   86  3   30.58783722 3   1   3   2013    7/24/2013   6/6/2006    307
c   15  3242    26.6435585  3   1   3   2014    7/24/2014   4/4/2004    359
e   67  1   22.95526123 3   1   4   2013    8/21/2013   5/5/2005    311
a   464 64  4.804824352 3   1   4   2014    8/20/2014   6/6/2006    363
b   66  42  29.42435265 3   1   5   2014    9/18/2014   7/7/2007    367
m   24  2   66.10663319 3   1   6   2014    10/13/2014  9/9/2009    371

示例输出(上面的最终代码):

colm.#1 colm.#10
a 6/6/2006
c 4/4/2004
d 3/3/2003
e 5/5/2005
b 7/7/2007
m 9/9/2009

最后,您可以添加.sort到上面最终代码的最后,以按a,b,c,d,e,m字母顺序对行进行排序,但(重要的是)这不是必需的。

https://raku.org

相关内容