Histogram o zmiennej szerokości
Histogram o zmiennej szerokości
Witam, potrzebuję stworzyć histogram w którym szerokość kolumn jest zmienna. Ma to wyglądać mniej więcej tak jak na załączonym poniżej obrazku. Czy ktoś wie może czy i jak można to zrobić?
LibreOffice Wersja: 6.1.4.2 na Windows 10
Re: Histogram o zmiennej szerokości
Ha! to jest jeden z moich ulubionych przykładów. Na taki wykres nie ma gotowca w Excelu ani w Calcu. Pokazuję czasem takie problemy studentom dla zachęty do uczenia się Matlaba, Scilaba, R-a, Pythona, albo choćby Gnuplota.
Skrypt w Python/Matplotlib mogę odgrzebać dość łatwo. Integracja z Calcem nie będzie prosta, ale przygotowanie grafiki na podstawie danych z pliku ods już tak. Z tym, że nie z poziomu Calc, tylko przez odczyt pliku innym narzędziem.
Zgodnie z pow. obietnicą, podsyłam mój `firmowy` przykład generowania podobnych wykresów funkcją pyplot.bar w Python + Matplotlib.
Źródła danych (do wyboru): albo Dane pochodzą -- już nie pamiętam -- albo z GUS-u, albo z statoids.com.
Kod skryptuoraz otrzymany z niego obrazek PNG
W razie potrzeby służę pomocą przy sczytaniu danych bezpośrednio z pliku Calca. Obrazki mogą powędrować do odrębnych plików graficznych; teoretycznie dałoby się je automatycznie osadzić w dokumencie, ale wymaga to grzebaniny. Gdyby obrazków było 200, zalecałbym podjęcie wysiłku; przy 20 raczej nie.
Możliwe jest też użycie podobnego skryptu jako makra w Calcu, choć wymaga to przekonfigurowania Pythona załączonego do LibreOffice (żeby doinstalować Matplotlib + zależności).
Ale zdaje mi się, że Twój wykres ma wadę konstrukcyjną. Histogram ma być graficznym przybliżeniem gęstości rozkładu, więc na osi liczbowej winna być zaznaczona intensywność. Jeśli jest to częstość bezwzględna podawana w dniach, to łączenie klas w szersze spowoduje wydłużanie słupków. A pożądane byłoby raczej ich uśrednianie.
Skrypt w Python/Matplotlib mogę odgrzebać dość łatwo. Integracja z Calcem nie będzie prosta, ale przygotowanie grafiki na podstawie danych z pliku ods już tak. Z tym, że nie z poziomu Calc, tylko przez odczyt pliku innym narzędziem.
Zgodnie z pow. obietnicą, podsyłam mój `firmowy` przykład generowania podobnych wykresów funkcją pyplot.bar w Python + Matplotlib.
Źródła danych (do wyboru): albo Dane pochodzą -- już nie pamiętam -- albo z GUS-u, albo z statoids.com.
Kod skryptu
Kod: Zaznacz cały
#!/usr/bin/env python3
"""
tworzenie wykresu na podstawie danych z bazy SQLite
przy użyciu pakietu Matplotlib/PyPlot
"""
import sqlite3
from matplotlib import pyplot
from matplotlib.font_manager import FontProperties
def z_bazy(rok):
baza = './woj.db'
# parametry zapytania
q = '''
select wojewodztwo as "Województwo",
powierzchnia as "Powierzchnia",
ludnosc as "Ludność"
from wojewodztwa
join wojpow using(klwoj)
join wojlud using(klwoj)
where rok = ?
order by ludnosc / powierzchnia desc;
'''
# nawiązanie połączenia
conn = sqlite3.connect(baza)
cursor = conn.cursor()
cursor.execute(q, (rok,))
data = cursor.fetchall()
conn.close()
return data
def z_pliku(rok, sep = '\t'):
nazwa = './woj.txt'
with open(nazwa) as f:
data = [ ]
f.readline()
for woj in f:
woj = woj.split(sep)
woj[1] = float(woj[1])
woj[2] = float(woj[2])
data.append(woj)
return data
def przygotuj(dane):
ludPL = 0
powPL = 0.0
powWoj = []
ludWoj = []
nazWoj = []
midWoj = []
poczWoj = [0.0]
for woj in dane:
powWoj.append(woj[1])
poczWoj.append(powPL + woj[1])
midWoj.append(powPL + 0.5*woj[1])
ludWoj.append(woj[2]/woj[1])
nazWoj.append(woj[0])
powPL += woj[1]
ludPL += woj[2]
ludPL = ludPL/powPL
poczWoj.pop(-1)
return poczWoj, midWoj, powWoj, ludWoj, nazWoj, powPL, ludPL
def rysuj(dane, rok):
# obróbka odpowiedzi
poczWoj, midWoj, powWoj, ludWoj, nazWoj, powPL, ludPL = przygotuj(dane)
# przygotowanie wykresu
fontFace = 'DejaVu Sans'
fopis = FontProperties()
fopis.set_family(fontFace)
fopis.set_size(8)
fnaglowek = FontProperties()
fnaglowek.set_family(fontFace)
fnaglowek.set_size(12)
kolory = ('#a0a0ff', '#ffa0a0')
opisy = ('województwa %s' % rok, 'Polska %s' % rok )
fig = pyplot.subplot(111)
fig.set_xlim(0.0, powPL)
fig.set_ylim(0.0, 500.0)
fig.set_title('Zaludnienie województw Polski', fontproperties = fnaglowek)
fig.set_xlabel('Powierzchnia', fontproperties = fnaglowek)
fig.set_ylabel('Gęstość zaludnienia [os./km^2]', fontproperties = fnaglowek)
pyplot.xticks(midWoj, nazWoj, fontproperties = fopis, rotation = 90)
fig.grid(axis = 'y')
# kreślenie serii danych
fig.bar(poczWoj, ludWoj, width = powWoj, align = "edge", color = kolory[0], edgecolor = 'black', label = opisy[0])
fig.bar((0.0), (ludPL), width=powPL, align = "edge", color = kolory[1], edgecolor = 'black', alpha = 0.2, label = opisy[1])
# legenda
fig.legend()
ltext = pyplot.gca().get_legend().get_texts()
pyplot.setp(ltext[0], fontproperties = fopis, color = kolory[0])
pyplot.setp(ltext[1], fontproperties = fopis, color = kolory[1])
rok = 2007
dane = z_bazy(rok)
rysuj(dane, rok)
pyplot.tight_layout()
pyplot.show()
Możliwe jest też użycie podobnego skryptu jako makra w Calcu, choć wymaga to przekonfigurowania Pythona załączonego do LibreOffice (żeby doinstalować Matplotlib + zależności).
Ale zdaje mi się, że Twój wykres ma wadę konstrukcyjną. Histogram ma być graficznym przybliżeniem gęstości rozkładu, więc na osi liczbowej winna być zaznaczona intensywność. Jeśli jest to częstość bezwzględna podawana w dniach, to łączenie klas w szersze spowoduje wydłużanie słupków. A pożądane byłoby raczej ich uśrednianie.
JJ
LO (7.6|24.2) ∙ Python (3.12|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
LO (7.6|24.2) ∙ Python (3.12|3.10) ∙ Unicode 15 ∙ LᴬTEX 2ε ∙ XML ∙ Unix tools ∙ Linux (Rocky|CentOS)
Re: Histogram o zmiennej szerokości
Dzięki wielkie, będę kombinował
LibreOffice Wersja: 6.1.4.2 na Windows 10