многосимвольный разделитель в `set разделителя файла данных" ||| "` не работает - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть входной файл example.data с тройным каналом в качестве разделителя, датами в первом столбце, а также некоторым более или менее непредсказуемым текстом в последнем столбце:

2019-02-01|||123|||345|||567|||Some unpredictable textual data with pipes|,
2019-02-02|||234|||345|||456|||weird symbols @ and commas, and so on.
2019-02-03|||345|||234|||123|||text text text

Когда я пытаюсьчтобы запустить следующий скрипт gnuplot5

set terminal png size 400,300
set output 'myplot.png'

set datafile separator "|||"
set xdata time
set timefmt "%Y-%m-%d"
set format x "%y-%m-%d"
plot "example.data" using 1:2 with linespoints

я получаю следующую ошибку:

line 8: warning: Skipping data file with no valid points

plot "example.data" using 1:2 with linespoints
                                              ^
"time.gnuplot", line 8: x range is invalid

Даже странно, если я изменю последнюю строку на

plot "example.data" using 1:4 with linespoints

тогдаоно работает.Это также работает для 1:7 и 1:10, но не для других чисел.Почему?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Вы в основном дали ответ сами.

  1. Если вы можете повлиять на разделитель в ваших данных, используйте разделитель, который обычно не встречается в ваших данных или тексте.Я всегда думал, что \t было сделано для этого.

  2. Если вы не можете влиять на разделитель в ваших данных, используйте внешний инструмент (awk, Python, Perl, ...) для измененияваши данные.В этих языках это, вероятно, «однострочник».У gnuplot нет функции прямой замены.

  3. Если вы не хотите устанавливать внешние инструменты и хотите гарантировать независимость от платформы, есть способ сделать это с помощью gnuplot.Это не просто «одна строка», но вы почти ничего не можете сделать с gnuplot; -).

Редактировать: упрощенная версия свходные данные @Ethan (https://stackoverflow.com/a/54541790/7295599).

Предполагается, что ваши данные находятся в наборе данных с именем $Data. Следующий код заменит ||| на \t и поместит результат в $DataOutput.

### Replace string in dataset
reset session

$Data <<EOD
# data with special string separators
2019-02-01|||123|||345|||567|||Some unpredictable textual data with pipes|,
2019-02-02|||234|||345|||456|||weird symbols @ and commas, and so on.
2019-02-03|||345|||234|||123|||text text text
EOD

# replace string function
# prefix RS_ to avoid variable name conflicts
replaceStr(s,s1,s2) = (RS_s='', RS_n=1, (sum[RS_i=1:strlen(s)] \
    ((s[RS_n:RS_n+strlen(s1)-1] eq s1 ? (RS_s=RS_s.s2, RS_n=RS_n+strlen(s1)) : \
    (RS_s=RS_s.s[RS_n:RS_n], RS_n=RS_n+1)), 0)), RS_s)

set print $DataOutput
do for [RS_j=1:|$Data|] {
    print replaceStr($Data[RS_j],"|||","\t")
}
set print

print $DataOutput
### end of code

Вывод:

# data with special string separators
2019-02-01  123 345 567 Some unpredictable textual data with pipes|,
2019-02-02  234 345 456 weird symbols @ and commas, and so on.
2019-02-03  345 234 123 text text text
0 голосов
/ 05 февраля 2019

При использовании синтаксиса

set datafile separator "chars"

строка не рассматривается как один длинный разделитель.Вместо этого каждый символ , указанный в кавычках, становится отдельным разделителем.От [Janert, 2016]:

Если вы укажете явную строку, то каждый символ в строке будет рассматриваться как символ-разделитель.

Следовательно,

set datafile separator "|||"

фактически эквивалентно

set datafile separator "|"

, а строка

2019-02-05|||123|||456|||789

обрабатывается так, как если бы она имела десять столбцов, из которых только столбцы 1,4,7,10 не пустые.


Обходной путь

Найдите какой-либо другой символ, который вряд ли появится в наборе данных (далее я будупредположим \t в качестве примера).Если вы не можете сбросить набор данных с помощью другого разделителя, используйте sed, чтобы заменить ||| на \t:

sed 's/|||/\t/g' example.data > modified.data # in the command line

, затем выполните

set datafile separator "\t"

и modified.data в качестве ввода.

...