Миллер: выбор столбцов на основе их последнего значения

Я обрабатываю файл TSV с сотней столбцов и хотел бы выбрать некоторые из них на основе их последних значений (т. е. значения в последней строке).

Например, со следующими данными (и я позволю вам представить еще 96 столбцов!):

      Year    An  Ti  Gi  Na
2000    5   10  2   3
2010    3   2   5   7
2020    6   3   5   6

Я хотел бы выбрать все столбцы, значение которых в последней строке не менее 5 (и, что еще лучше, я хотел бы выбрать все столбцы, значение которых в последней строке не меньше значения строки Gi).

Итак, в конце концов я хотел бы получить следующий результат (столбец Ti отбрасывается, поскольку его значение в последней строке равно 3, что ниже нашего порога).

      Year    An  Gi  Na
2000    5   2   3
2010    3   5   7
2020    6   5   6

Есть ли у вас какие-либо идеи?

Спасибо!

2 ответа

Вы можете написать этот bash-скрипт

      #!/bin/bash

gi_value=$(mlr --t2n tail -n 1 then cut -f Gi input.tsv)

gi_columns=$(mlr --t2n tail -n 1 then label 1 then reshape -r '^[a-zA-Z]' -o k,v then filter '$v >= '"$gi_value"'' then cut -f k then nest --ivar "," -f k input.tsv)

mlr --tsv cut -f Year,"$gi_columns" input.tsv

Сначала извлеките значение Gi

      mlr --t2n tail -n 1 then cut -f Gi input.tsv

заселитьgi_valueвар с5ценить.

Затем извлеките список столбцов последней строки, в которой значение >= 5.

      mlr --t2n tail -n 1 \
then label 1 \
then reshape -r '^[a-zA-Z]' -o k,v \
then filter '$v >= '"$gi_value"'' \
then cut -f k \
then nest --ivar "," -f k input.tsv

Это дает вам результат.

Последний шаг – разрезатьAn,Gi,Naстолбцы:

      mlr --tsv cut -f Year,"$gi_columns" input.tsv

Результат:

      Year    An      Gi      Na
2000    5       2       3
2010    3       5       7
2020    6       5       6

Вы можете использовать небольшую программу DSL для выбора/вырезания полей. Обратной стороной является то, что он загружает весь файл в ОЗУ (это то, что я наблюдал приmlrтекущая реализация):

      mlr --tsv tac then put '
    is_null(@m) { @m = apply($*, func(k,v) { return {k: v >= $Gi}; }); }
    $* = select($*, func(k,v) { return @m[k]; });
' file.tsv
      Year    An  Gi  Na
2020    6   5   6
2010    3   5   7
2000    5   2   3

Примечание: порядок записей в выводе меняется на обратный, поэтому вы можете добавить еще одинtacк цепочке для возврата исходного заказа:

      mlr --tsv tac then put '...' then tac file.tsv
Другие вопросы по тегам