У меня есть данные cvs из sqlite3, небольшой отредактированный образец:
Если я построю столбцы 3+ против 1, все будет хорошо. Я просто хотел бы узнать, где находятся дни (в идеале начало каждого дня) по оси X, но я не хочу, чтобы каждая точка данных имела одну и ту же метку даты.
conTime настраивается в sql, чтобы дать мне плавно увеличивающееся число с соответствующей степенью детализации для моих нужд, поэтому мне действительно нужно, чтобы это было основой оси X.
В псевдокоде я хотел бы (график) метка columns_text(2) точки данных 20; или (график) label columns_text(2) at col(1),-15 'когда он меняется';
Я провел много часов, играя с идеями с www. Текущие их остатки приведены ниже, я в основном вырезаю и вставляю их в интерактивном режиме в сеансы Gnuplot... Если бы у меня работали xticlabels или что-то подобное, их было бы слишком много. Генерация в sql нулевой или измененной даты может сработать, но это также обучение этому и побочный путь от того, чего мне нужно достичь...
set xdata time
set timefmt "%Y/%m/%d"
set format x "%Y-%m-%d"
set xtics rotate by 90 offset 0,-4
#plot first line heavier weight as clearer ref etc.
#plot "sqlout.csv" using 1:2 with text dp 10, \
plot "sqlout.csv" using 1:3 with lp lt 1 lw 3 title columnhead(3), \
"sqlout.csv" using 1:4 with lp lt 2 lw 3 title columnhead(4), \
for [col=5:*] "sqlout.csv" using 1:col with lp ls col title columnhead(col)
#pause -1 "Return to end..."
#pause 2
plot "sqlout.csv" using 2:3 with lp lt 1 lw 3 title columnhead(3), \
"sqlout.csv" using 2:4 with lp lt 2 lw 3 title columnhead(4), \
for [col=5:*] "sqlout.csv" using 2:col with lp ls col title columnhead(col)
Кстати заставить таблицу работать удалось PITA, добавив | в SQL. БОЛЬШАЯ ПОДСКАЗКА: | ---| --- | клетки кажутся необходимыми???
С момента публикации мне удалось в sql использовать LAG(dayXS_date) только для того, чтобы показывать, где меняются даты, и оставить пустым в противном случае, поэтому построение графика всей оси теперь решило бы и мою проблему. Я даже не знаю, как это сделать!
Кажется, я не могу составить здесь таблицу с пустыми ячейками! Превью Отлично!
Это было то, что я попробовал в первую очередь, но, похоже, строки объединялись независимо от того, какой стиль цитаты и т. д. я пробовал. может быть, это потому, что он ожидает окончания строк в стиле Windows? Я использую MacOS, поэтому по умолчанию стиль *nix. Но спасибо, я так и думал...
Если вы посмотрите на мой SQL ниже, мне действительно нужно собрать строки в столбцы. Для меня это пустая трата времени, особенно когда есть 10*2 категории! Есть ли способ, которым Gnuplot может обрабатывать чтение категории из столбца locationID и при этом выдавать тот же результат? Итак, мои строки данных будут иметь столбцы: ..... conTime, дата, местоположение, AH, Cx10.
Я не знаю SQL, поэтому не понимаю, о чем вы. Если это новая тема, задайте новый вопрос с четким примером входных данных и подробным описанием желаемого выходного графика (и в идеале с помощью сценария gnuplot).
На данный момент я понимаю ваш вопрос следующим образом: у вас есть некоторые данные о времени, но у данных есть только отметка дня (нет времени в часах/минутах). Поскольку существует несколько точек данных за один и тот же день, они будут отображаться в одной и той же позиции на оси времени. Поскольку вы хотите распределить данные, вы ввели столбец conTime
, чтобы немного распределить точки данных. Теперь вопрос в том, как распределить данные в течение дня, верно?
Некоторые комментарии:
smooth freq
подсчитывается количество точек данных за каждый день. Блок данных $Counts
будет содержать время (в секундах, прошедших с 1 января 1970 года) и количество точек данных.getCounts()
— это функция «поиска», позволяющая получить количество данных в зависимости от дня.spread()
инициализирует счетчик c=0
и увеличивает его на 1 каждый раз, когда предыдущее время t0
идентично текущему времени t1
. Каждый раз, когда наступает новый день, счетчик сбрасывается на c=0
, а c0
получает количество точек данных за этот день. Функция фактически вернет дробь 86400.*c/c0
, т.е. данные распределены по дням (86400 секунд = 1 день).Возможно, это еще можно упростить.
Данные: SO78513320.csv
Просто для иллюстрации я ввел некоторые дополнительные данные, разделенные закомментированными строками для наглядности.
conTime,dayXS_date,Ref-AHx,Ref-Cx10,Bed1-AH,Bed2-AH,Bed1-Cx10,Bed2-Cx10
6466,2024/05/14,510,149,583,604,210,222
6467,2024/05/14,510,147,587,601,210,221
6468,2024/05/14,515,143,590,599,210,220
6469,2024/05/14,515,144,582,597,209,220
6470,2024/05/14,517,144,589,596,209,219
6471,2024/05/14,526,144,586,594,208,219
6472,2024/05/14,538,139,583,590,207,218
6473,2024/05/14,542,135,581,587,206,217
6474,2024/05/14,542,134,597,584,205,216
6475,2024/05/14,538,133,597,580,205,215
#
6480,2024/05/17,538,133,597,580,205,215
6480,2024/05/17,528,143,587,570,215,225
6480,2024/05/17,518,153,577,560,225,235
6480,2024/05/17,538,133,597,580,205,215
#
6690,2024/05/20,466,206,638,602,232,235
6691,2024/05/20,486,197,651,600,236,240
6692,2024/05/20,510,189,646,640,236,241
6693,2024/05/20,506,181,638,657,235,241
6694,2024/05/20,527,171,613,630,234,238
6695,2024/05/20,528,159,605,662,232,238
6696,2024/05/20,507,145,593,658,230,235
6697,2024/05/20,493,136,587,647,228,232
6698,2024/05/20,485,131,585,587,227,227
6699,2024/05/20,500,133,585,628,226,229
Скрипт:
### spread data of one day over 24 hours
reset session
FILE = "SO78513320.csv"
set datafile separator comma
myFmt = "%Y/%m/%d"
set table $Counts
set format x "%.0f"
plot FILE u (timecolumn(2,myFmt)):(1) smooth freq
unset table
getCounts(t) = sum [i=5:|$Counts|-2] ($Counts[i]==t ? int(word($Counts[i],2)) : 0)
spread(col) = (t=timecolumn(col,myFmt), $0==0 ? (c=0, c0=getCounts(t),t1=t) : NaN, \
t0=t1, t1=t, t0==t1 ? c=c+1 : (c=0, c0=getCounts(t)), t+86400.*c/c0)
set format x "%Y\n%m/%d" timedate
set offsets graph 0.05, graph 0.05, graph 0.05, graph 0.05
set key out
set grid x,y
plot FILE u (spread(2)):3 w lp pt 7 lw 3 ti columnhead, \
'' u (spread(2)):4 w lp pt 7 lw 3 ti columnhead, \
for [i=5:*] '' u (spread(2)):i w lp pt 7 lw 1 ti columnhead
### end of script
Результат:
Добавление:
Немного более простой сценарий, если вы предполагаете фиксированное максимальное количество точек данных в день (здесь: c0=20
).
Скрипт:
### spread data of one day over 24 hours
reset session
FILE = "SO78513320.csv"
set datafile separator comma
myFmt = "%Y/%m/%d"
set format x "%Y\n%m/%d" timedate
set offsets graph 0.05, graph 0.05, graph 0.05, graph 0.05
set key out
set grid x,y
c0 = 20 # max. datapoints per day
spread(col) = (t=timecolumn(col,myFmt), $0==0 ? (c=0, t1=t) : NaN, \
t0=t1, t1=t, t0==t1 ? c=c+1 : c=0, t+86400.*c/c0)
plot FILE u (spread(2)):3 w lp pt 7 lw 3 ti columnhead, \
'' u (spread(2)):4 w lp pt 7 lw 3 ti columnhead, \
for [i=5:*] '' u (spread(2)):i w lp pt 7 lw 1 ti columnhead
### end of script
Результат:
Это все отличные и полезные примеры функций, о существовании которых я даже не подозревал. Я буду публиковать то, что я сделал сам, чтобы приблизиться к решению, поскольку это также может быть полезно для аудитории... Мне может потребоваться некоторое время, чтобы усвоить все и решить, какой лучший способ продолжить работу с такого рода работа.... Есть много других функций, которые вы использовали, которые мне нравятся, например, сетка
Что касается данных о времени: фактически у меня есть слот с номером 0–143 для 10-минутных сегментов в течение дня. Это добавляется к 1000 x целочисленному дню с тех пор, как я начал записывать данные, поэтому у меня есть timeID, целое число для компактности, но я могу ссылаться на таблицу информации о дне с текстом даты и несколькими другими соответствующими фактами о дне (например, вывод PVpanels , осадки, примечания)
Еще многому предстоит научиться и усвоить то, что вы дали! Сеанс сброса, таблицы, почему $ в $Counts мне нужно оформить заказ и т. д. и т. п. Огромное спасибо... Метод распространения немного неправильно рисовал, когда точки данных не собирались из-за сбоев Интернета/ISP-сервера - таких было несколько. сбои в передаче данных.... Данные, использующие номер слота, будут в правильном месте. Я, конечно, могу установить c0 на 143!
Я не уверен, как будет работать более простой код, в котором я усредняю интервалы, чтобы получить меньше точек данных в день при построении графика более длительных периодов? [Но, возможно, это мое нынешнее невежество!] то есть, если я сохраню общий код сценария Gnuplot для использования для различных выходных данных sql, то количество точек данных в день будет меняться, но никогда не превысит 144 (от 0 до 143).
На самом деле мне нужно построить гораздо больше рядов данных, около 20, и для большого количества SQL-запросов. Вызывается ли функция распространения(2) и запускается каждый раз, если да, то можно ли этого избежать, сохранив в таблице только один раз? Я знаю, что все серии должны иметь одинаковое количество считываний (если нет физического повреждения), даже если в идеале код Gnuplot не будет сообщен моим редактированием перед запуском, что это за число.
Если немного поразмыслить, становится очевидным, что более простой код сожмет меньшее количество точек в первую часть дня... Документация по установленной таблице интересна, поэтому мы выводим результат в таблицу (я предполагаю, в памяти), а затем читаем это позже.
@Cwinte, чтобы проверить, что может пойти не так, покажите пример данных, для которых сценарий «слегка неправильно рисует» данные. Функция spread()
в первом примере предназначена именно для случая, если в день имеются точки данных переменного типа. Эти числа хранятся в блоке данных $Counts
. В консоли gnuplot после запуска скрипта введите print $Counts
, чтобы увидеть.
Пока я ждал ответов, я пытался сделать больше в SQL. Мне удалось получить изменения дня только в столбце... но возникли проблемы, поскольку пробелы игнорировались, и Gnuplot брал данные из следующего столбца справа, что на некоторое время смутило меня. В конце концов я получил SQL, чтобы дать файл . когда дата была та же самая, и все было неплохо.
# time based data, date text in column 2 while 1 is numeric of some kind (sorted but not user friendly)
set term pdfcairo size 17in, 12in
fdate=system("date +%F,%H.%M")
set output sprintf('./sql2dyQRY%s.pdf', fdate)
set key outside
set size 0.98, 0.98
set title "col2day SQLqry ".fdate font ",25";
#plot first line heavier weight as clearer ref etc. Set y= (300) to position between my data areas
plot "sqlout.csv" using 1:(300):2 with labels rotate notitle, \
"sqlout.csv" using 1:3 with lp lt 1 lw 3 title columnhead(3), \
"sqlout.csv" using 1:4 with lp lt 2 lw 3 title columnhead(4), \
for [col=5:*] "sqlout.csv" using 1:col with lp ls col title columnhead(col);
unset output
выберите cast((timeID+(timeID%1000)*5.94)/30 как int) как "conTime", IIF(dayXS_date=LAG(dayXS_date)over(order by dayID),'.', dayXS_date) как dateLbl, cast(avg (IIF(locationID=1,AHx100/2,NULL)) как int) как "Ref-AHx", cast(avg(IIF(locationID=1,Cx10,NULL)) как int) как "Ref-Cx10", cast (avg(IIF(locationID=3,AHx100/2,NULL)) как int) как "Bed1-AH", cast(avg(IIF(locationID=7,AHx100/2,NULL)) как int) как "Bed2- AH", cast(avg(IIF(locationID=3,Cx10,NULL)) как int) как "Bed1-Cx10", cast(avg(IIF(locationID=7,Cx10,NULL)) как int) как "Bed2- Cx10" из истории, DayInfo, где timeID>193999 и dayID=cast(timeID/1000 as int) группируются по "conTime";
conTime dateLbl Ref-AHx Ref-Cx10 Bed1-AH Bed2-AH Bed1-Cx10 Bed2-Cx10
------- ---------- ------- -------- ------- ------- --------- ---------
6466 2024/05/14 510 149 583 604 210 222
6467 . 510 147 587 601 210 221
6468 . 515 143 590 599 210 220
6469 . 515 144 582 597 209 220
6470 . 517 144 589 596 209 219
Зачем создавать сложную таблицу, если ваши данные представляют собой простой текстовый файл, например CSV? Просто скопируйте и вставьте свой CSV-файл сюда, на StackOverflow, между парой тройных обратных кавычек. Насколько я понимаю, вы хотите построить график ежедневных данных с небольшим сдвигом во времени, верно? Сколько точек данных обычно находится в течение одного дня? Это фиксированное число или переменная в определенном диапазоне?