Сортировка данных с помощью gnuplot - PullRequest
0 голосов
/ 11 января 2019

Иногда может потребоваться сортировка данных. К сожалению, gnuplot (насколько я знаю) не предлагает такую ​​возможность. Конечно, вы можете использовать внешние инструменты, такие как awk, Perl, Python и т. Д. Однако для максимальной независимости платформы и избежания установки дополнительных программ и связанных с этим сложностей, а также для любопытства мне было интересно, может ли gnuplot все-таки сортировать. Буду благодарен за комментарии по улучшениям, ограничениям.

У кого-нибудь есть идеи, как сортировать буквенно-цифровые данные только с помощью gnuplot?

### Sorting with gnuplot
reset session

# generate some random example data
N = 10
set samples N
RandomNo(n) = sprintf("%.02f",rand(0)*n)
set table $Data
    plot '+' u (RandomNo(10)):(RandomNo(10)):(RandomNo(10)) w table
unset table
print $Data

# Settings for sorting
ColNo = 2   # ColumnNo for sorting
stats $Data nooutput      # get the number of rows if data is from file
RowCount = STATS_records  # with the example data above, of course RowCount=N

# create the sortkey and put it into an array
array SortKey[RowCount]
set table $Dummy
    plot $Data u (SortKey[$0+1] = sprintf("%.06f%02d",column(ColNo),$0+1)) w table
unset table
# print $Dummy

# get lines as whole into array
set datafile separator "\n"
array DataSeq[RowCount]
set table $Dummy2
    plot $Data u (SortKey[$0+1]):(DataSeq[$0+1] = stringcolumn(1)) with table
unset table
print $Dummy2
set datafile separator whitespace

# do the actual sorting with 'smooth unique'
set table $Dummy3
    plot $Dummy2 u 1:0 smooth unique
unset table
# print $Dummy3

# extract the sorted sortkeys
set table $Dummy4
    plot $Dummy3 u (SortKey[$0+1]=$2) with table
unset table
# print $Dummy4

# create the table with sorted lines
set table $DataSorted
    plot $Data u (DataSeq[SortKey[$0+1]+1]) with table
unset table
print $DataSorted
### end of code
  • Первый блок данных несортированных данных
  • второй промежуточный блок данных с сортировочными клавишами
  • третий блок данных, отсортированный по второму столбцу

Выход:

 5.24    6.68    3.09   
 1.64    1.27    9.82   
 6.44    9.23    7.03   
 8.14    8.87    3.82   
 4.27    5.98    0.93   
 7.96    3.64    6.15   
 6.21    6.28    6.17   
 1.52    3.17    3.58   
 4.24    2.16    8.99   
 8.73    6.54    1.13   

 6.68000001      5.24    6.68    3.09
 1.27000002      1.64    1.27    9.82
 9.23000003      6.44    9.23    7.03
 8.87000004      8.14    8.87    3.82
 5.98000005      4.27    5.98    0.93
 3.64000006      7.96    3.64    6.15
 6.28000007      6.21    6.28    6.17
 3.17000008      1.52    3.17    3.58
 2.16000009      4.24    2.16    8.99
 6.54000010      8.73    6.54    1.13

 1.64    1.27    9.82
 4.24    2.16    8.99
 1.52    3.17    3.58
 7.96    3.64    6.15
 4.27    5.98    0.93
 6.21    6.28    6.17
 8.73    6.54    1.13
 5.24    6.68    3.09
 8.14    8.87    3.82
 6.44    9.23    7.03 

1 Ответ

0 голосов
/ 18 января 2019

Для любопытства я хотел знать, может ли буквенно-цифровая сортировка быть реализована только с помощью кода gnuplot. Это позволяет избежать необходимости использования внешних инструментов и обеспечивает максимальную совместимость с платформой. Я еще не слышал о внешнем инструменте, который мог бы помочь gnuplot и который работает под Windows и Linux и MacOS. Я рад принимать комментарии и предложения об ошибках, упрощениях, улучшениях, сравнении производительности и ограничениях.

Для буквенно-цифровой сортировки первым этапом является буквенно-цифровое сравнение строк, которое, насколько мне известно, не существует в gnuplot напрямую. Итак, первая часть Compare.plt посвящена сравнению строк.

### compare function for strings 
# Compare.plt
# function cmp(a,b,cs) returns a<b:-1, a==b:0, a>b:+1
# cs=0: case-insensitive, cs=1: case-sensitive
reset session

ASCII =  ' !"' . "#$%&'()*+,-./0123456789:;<=>?@".\
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`".\
         "abcdefghijklmnopqrstuvwxyz{|}~"

ord(c) = strstrt(ASCII,c)>0 ? strstrt(ASCII,c)+31 : 0

# comparing char: case-sensitive
cmpcharcs(c1,c2) = sgn(ord(c1)-ord(c2))

# comparing char: case-insentitive
cmpcharci(c1,c2) = sgn(( cmpcharci_o1=ord(c1), ((cmpcharci_o1>96) && (cmpcharci_o1<123)) ?\
    cmpcharci_o1-32 : cmpcharci_o1) - \
    ( cmpcharci_o2=ord(c2), ((cmpcharci_o2>96) && (cmpcharci_o2<123)) ?\
    cmpcharci_o2-32 : cmpcharci_o2) )

# function cmp returns a<b:-1, a==b:0, a>b:+1
# cs=0: case-insensitive, cs=1: case-sensitive
cmp(a,b,cs) = ((cmp_r=0, cmp_flag=0, cmp_maxlen=strlen(a)>strlen(b) ? strlen(a) : strlen(b)),\
    (sum[cmp_i=1:cmp_maxlen] \
      ((cmp_flag==0 && (cmp_c1 = substr(a,cmp_i,cmp_i), cmp_c2 = substr(b,cmp_i,cmp_i), \
        (cmp_r = (cs==0 ?  cmpcharci(cmp_c1,cmp_c2) : cmpcharcs(cmp_c1,cmp_c2) ) )!=0 ? \
        (cmp_flag=1, cmp_r) : 0)), 1 )), cmp_r)

cmpsymb(a,b,cs) = (cmpsymb_r = cmp(a,b,cs))<0 ? "<" : cmpsymb_r>0 ? ">" : "="
### end of code

Пример:

### example compare strings
load "Compare.plt"

a="Alligator"
b="Tiger"
print sprintf("% 2d: % 9s% 2s% 6s", cmp(a,b,0), a, cmpsymb(a,b,0), b)

a="Tiger"
print sprintf("% 2d: % 9s% 2s% 6s", cmp(a,b,0), a, cmpsymb(a,b,0), b)

a="Zebra"
print sprintf("% 2d: % 9s% 2s% 6s", cmp(a,b,0), a, cmpsymb(a,b,0), b)
### end of code

Результат:

-1: Alligator < Tiger
 0:     Tiger = Tiger
 1:     Zebra > Tiger

Вторая часть использует сравнение для сортировки.

### alpha-numerical sort with gnuplot
reset session
load "Compare.plt"

$Data <<EOD
1   0.123   Orange
2   0.456   Apple
3   0.789   Peach
4   0.987   Pineapple
5   0.654   Banana
6   0.321   Raspberry
7   0.111   Lemon
EOD

stats $Data u 0 nooutput
RowCount = STATS_records
ColSort = 3

array Key[RowCount]
array Index[RowCount]

set table $Dummy
    plot $Data u (Key[$0+1]=stringcolumn(ColSort),Index[$0+1]=$0+1) w table
unset table

# Bubblesort
do for [n=RowCount:2:-1] {
    do for [i=1:n-1] {
        if ( cmp(Key[i],Key[i+1],0) > 0) { 
            tmp=Key[i]; Key[i]=Key[i+1]; Key[i+1]=tmp
            tmp2=Index[i]; Index[i]=Index[i+1]; Index[i+1]=tmp2
        }
    }
}

set datafile separator "\n"
set table $Dummy    # and reuse Key-array
    plot $Data u (Key[$0+1]=stringcolumn(1)) with table
unset table
set datafile separator whitespace

set table $DataSorted
    plot $Data u (Key[Index[$0+1]]) with table
unset table

print $DataSorted
set grid xtics,ytics
plot [-0.5:RowCount-0.5][0:1.1] $DataSorted u 0:2:xtic(3) w lp lt 7 lc rgb "red"
### end of code

Введите:

1   0.123   Orange
2   0.456   Apple
3   0.789   Peach
4   0.987   Pineapple
5   0.654   Banana
6   0.321   Raspberry
7   0.111   Lemon

Выход:

 2      0.456   Apple   
 5      0.654   Banana  
 7      0.111   Lemon   
 1      0.123   Orange  
 3      0.789   Peach   
 4      0.987   Pineapple       
 6      0.321   Raspberry  

и выходной график:

enter image description here

...