From 698abaa406151477d7f6c3581e3bfb1c9b9d23f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Bruer-Skarsb=C3=B8?= Date: Fri, 12 Jan 2024 22:28:45 +0100 Subject: [PATCH] Added blog --- .../site_libs/quarto-listing/list.min.js | 2 + .../quarto-listing/quarto-listing.js | 243 ++++++++++++++++++ dapla-manual/_quarto.yml | 2 + dapla-manual/blog/index.qmd | 16 ++ .../fame.png | Bin 0 -> 6103 bytes .../index.qmd | 95 +++++++ 6 files changed, 358 insertions(+) create mode 100644 dapla-manual/_freeze/site_libs/quarto-listing/list.min.js create mode 100644 dapla-manual/_freeze/site_libs/quarto-listing/quarto-listing.js create mode 100644 dapla-manual/blog/index.qmd create mode 100644 dapla-manual/blog/posts/2023-01-12-jupyter-cell-embedding/fame.png create mode 100644 dapla-manual/blog/posts/2023-01-12-jupyter-cell-embedding/index.qmd diff --git a/dapla-manual/_freeze/site_libs/quarto-listing/list.min.js b/dapla-manual/_freeze/site_libs/quarto-listing/list.min.js new file mode 100644 index 00000000..81318815 --- /dev/null +++ b/dapla-manual/_freeze/site_libs/quarto-listing/list.min.js @@ -0,0 +1,2 @@ +var List;List=function(){var t={"./src/add-async.js":function(t){t.exports=function(t){return function e(r,n,s){var i=r.splice(0,50);s=(s=s||[]).concat(t.add(i)),r.length>0?setTimeout((function(){e(r,n,s)}),1):(t.update(),n(s))}}},"./src/filter.js":function(t){t.exports=function(t){return t.handlers.filterStart=t.handlers.filterStart||[],t.handlers.filterComplete=t.handlers.filterComplete||[],function(e){if(t.trigger("filterStart"),t.i=1,t.reset.filter(),void 0===e)t.filtered=!1;else{t.filtered=!0;for(var r=t.items,n=0,s=r.length;nv.page,a=new g(t[s],void 0,n),v.items.push(a),r.push(a)}return v.update(),r}m(t.slice(0),e)}},this.show=function(t,e){return this.i=t,this.page=e,v.update(),v},this.remove=function(t,e,r){for(var n=0,s=0,i=v.items.length;s-1&&r.splice(n,1),v},this.trigger=function(t){for(var e=v.handlers[t].length;e--;)v.handlers[t][e](v);return v},this.reset={filter:function(){for(var t=v.items,e=t.length;e--;)t[e].filtered=!1;return v},search:function(){for(var t=v.items,e=t.length;e--;)t[e].found=!1;return v}},this.update=function(){var t=v.items,e=t.length;v.visibleItems=[],v.matchingItems=[],v.templater.clear();for(var r=0;r=v.i&&v.visibleItems.lengthe},innerWindow:function(t,e,r){return t>=e-r&&t<=e+r},dotted:function(t,e,r,n,s,i,a){return this.dottedLeft(t,e,r,n,s,i)||this.dottedRight(t,e,r,n,s,i,a)},dottedLeft:function(t,e,r,n,s,i){return e==r+1&&!this.innerWindow(e,s,i)&&!this.right(e,n)},dottedRight:function(t,e,r,n,s,i,a){return!t.items[a-1].values().dotted&&(e==n&&!this.innerWindow(e,s,i)&&!this.right(e,n))}};return function(e){var n=new i(t.listContainer.id,{listClass:e.paginationClass||"pagination",item:e.item||"
  • ",valueNames:["page","dotted"],searchClass:"pagination-search-that-is-not-supposed-to-exist",sortClass:"pagination-sort-that-is-not-supposed-to-exist"});s.bind(n.listContainer,"click",(function(e){var r=e.target||e.srcElement,n=t.utils.getAttribute(r,"data-page"),s=t.utils.getAttribute(r,"data-i");s&&t.show((s-1)*n+1,n)})),t.on("updated",(function(){r(n,e)})),r(n,e)}}},"./src/parse.js":function(t,e,r){t.exports=function(t){var e=r("./src/item.js")(t),n=function(r,n){for(var s=0,i=r.length;s0?setTimeout((function(){e(r,s)}),1):(t.update(),t.trigger("parseComplete"))};return t.handlers.parseComplete=t.handlers.parseComplete||[],function(){var e=function(t){for(var e=t.childNodes,r=[],n=0,s=e.length;n]/g.exec(t)){var e=document.createElement("tbody");return e.innerHTML=t,e.firstElementChild}if(-1!==t.indexOf("<")){var r=document.createElement("div");return r.innerHTML=t,r.firstElementChild}}},a=function(e,r,n){var s=void 0,i=function(e){for(var r=0,n=t.valueNames.length;r=1;)t.list.removeChild(t.list.firstChild)},function(){var r;if("function"!=typeof t.item){if(!(r="string"==typeof t.item?-1===t.item.indexOf("<")?document.getElementById(t.item):i(t.item):s()))throw new Error("The list needs to have at least one item on init otherwise you'll have to add a template.");r=n(r,t.valueNames),e=function(){return r.cloneNode(!0)}}else e=function(e){var r=t.item(e);return i(r)}}()};t.exports=function(t){return new e(t)}},"./src/utils/classes.js":function(t,e,r){var n=r("./src/utils/index-of.js"),s=/\s+/;Object.prototype.toString;function i(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}t.exports=function(t){return new i(t)},i.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array();return~n(e,t)||e.push(t),this.el.className=e.join(" "),this},i.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=n(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},i.prototype.toggle=function(t,e){return this.list?(void 0!==e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):(void 0!==e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},i.prototype.array=function(){var t=(this.el.getAttribute("class")||"").replace(/^\s+|\s+$/g,"").split(s);return""===t[0]&&t.shift(),t},i.prototype.has=i.prototype.contains=function(t){return this.list?this.list.contains(t):!!~n(this.array(),t)}},"./src/utils/events.js":function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",s=window.removeEventListener?"removeEventListener":"detachEvent",i="addEventListener"!==n?"on":"",a=r("./src/utils/to-array.js");e.bind=function(t,e,r,s){for(var o=0,l=(t=a(t)).length;o32)return!1;var a=n,o=function(){var t,r={};for(t=0;t=p;b--){var j=o[t.charAt(b-1)];if(C[b]=0===m?(C[b+1]<<1|1)&j:(C[b+1]<<1|1)&j|(v[b+1]|v[b])<<1|1|v[b+1],C[b]&d){var x=l(m,b-1);if(x<=u){if(u=x,!((c=b-1)>a))break;p=Math.max(1,2*a-c)}}}if(l(m+1,a)>u)break;v=C}return!(c<0)}},"./src/utils/get-attribute.js":function(t){t.exports=function(t,e){var r=t.getAttribute&&t.getAttribute(e)||null;if(!r)for(var n=t.attributes,s=n.length,i=0;i=48&&t<=57}function i(t,e){for(var i=(t+="").length,a=(e+="").length,o=0,l=0;o=i&&l=a?-1:l>=a&&o=i?1:i-a}i.caseInsensitive=i.i=function(t,e){return i((""+t).toLowerCase(),(""+e).toLowerCase())},Object.defineProperties(i,{alphabet:{get:function(){return e},set:function(t){r=[];var s=0;if(e=t)for(;s { + if (categoriesLoaded) { + activateCategory(category); + setCategoryHash(category); + } +}; + +window["quarto-listing-loaded"] = () => { + // Process any existing hash + const hash = getHash(); + + if (hash) { + // If there is a category, switch to that + if (hash.category) { + activateCategory(hash.category); + } + // Paginate a specific listing + const listingIds = Object.keys(window["quarto-listings"]); + for (const listingId of listingIds) { + const page = hash[getListingPageKey(listingId)]; + if (page) { + showPage(listingId, page); + } + } + } + + const listingIds = Object.keys(window["quarto-listings"]); + for (const listingId of listingIds) { + // The actual list + const list = window["quarto-listings"][listingId]; + + // Update the handlers for pagination events + refreshPaginationHandlers(listingId); + + // Render any visible items that need it + renderVisibleProgressiveImages(list); + + // Whenever the list is updated, we also need to + // attach handlers to the new pagination elements + // and refresh any newly visible items. + list.on("updated", function () { + renderVisibleProgressiveImages(list); + setTimeout(() => refreshPaginationHandlers(listingId)); + + // Show or hide the no matching message + toggleNoMatchingMessage(list); + }); + } +}; + +window.document.addEventListener("DOMContentLoaded", function (_event) { + // Attach click handlers to categories + const categoryEls = window.document.querySelectorAll( + ".quarto-listing-category .category" + ); + + for (const categoryEl of categoryEls) { + const category = categoryEl.getAttribute("data-category"); + categoryEl.onclick = () => { + activateCategory(category); + setCategoryHash(category); + }; + } + + // Attach a click handler to the category title + // (there should be only one, but since it is a class name, handle N) + const categoryTitleEls = window.document.querySelectorAll( + ".quarto-listing-category-title" + ); + for (const categoryTitleEl of categoryTitleEls) { + categoryTitleEl.onclick = () => { + activateCategory(""); + setCategoryHash(""); + }; + } + + categoriesLoaded = true; +}); + +function toggleNoMatchingMessage(list) { + const selector = `#${list.listContainer.id} .listing-no-matching`; + const noMatchingEl = window.document.querySelector(selector); + if (noMatchingEl) { + if (list.visibleItems.length === 0) { + noMatchingEl.classList.remove("d-none"); + } else { + if (!noMatchingEl.classList.contains("d-none")) { + noMatchingEl.classList.add("d-none"); + } + } + } +} + +function setCategoryHash(category) { + setHash({ category }); +} + +function setPageHash(listingId, page) { + const currentHash = getHash() || {}; + currentHash[getListingPageKey(listingId)] = page; + setHash(currentHash); +} + +function getListingPageKey(listingId) { + return `${listingId}-page`; +} + +function refreshPaginationHandlers(listingId) { + const listingEl = window.document.getElementById(listingId); + const paginationEls = listingEl.querySelectorAll( + ".pagination li.page-item:not(.disabled) .page.page-link" + ); + for (const paginationEl of paginationEls) { + paginationEl.onclick = (sender) => { + setPageHash(listingId, sender.target.getAttribute("data-i")); + showPage(listingId, sender.target.getAttribute("data-i")); + return false; + }; + } +} + +function renderVisibleProgressiveImages(list) { + // Run through the visible items and render any progressive images + for (const item of list.visibleItems) { + const itemEl = item.elm; + if (itemEl) { + const progressiveImgs = itemEl.querySelectorAll( + `img[${kProgressiveAttr}]` + ); + for (const progressiveImg of progressiveImgs) { + const srcValue = progressiveImg.getAttribute(kProgressiveAttr); + if (srcValue) { + progressiveImg.setAttribute("src", srcValue); + } + progressiveImg.removeAttribute(kProgressiveAttr); + } + } + } +} + +function getHash() { + // Hashes are of the form + // #name:value|name1:value1|name2:value2 + const currentUrl = new URL(window.location); + const hashRaw = currentUrl.hash ? currentUrl.hash.slice(1) : undefined; + return parseHash(hashRaw); +} + +const kAnd = "&"; +const kEquals = "="; + +function parseHash(hash) { + if (!hash) { + return undefined; + } + const hasValuesStrs = hash.split(kAnd); + const hashValues = hasValuesStrs + .map((hashValueStr) => { + const vals = hashValueStr.split(kEquals); + if (vals.length === 2) { + return { name: vals[0], value: vals[1] }; + } else { + return undefined; + } + }) + .filter((value) => { + return value !== undefined; + }); + + const hashObj = {}; + hashValues.forEach((hashValue) => { + hashObj[hashValue.name] = decodeURIComponent(hashValue.value); + }); + return hashObj; +} + +function makeHash(obj) { + return Object.keys(obj) + .map((key) => { + return `${key}${kEquals}${obj[key]}`; + }) + .join(kAnd); +} + +function setHash(obj) { + const hash = makeHash(obj); + window.history.pushState(null, null, `#${hash}`); +} + +function showPage(listingId, page) { + const list = window["quarto-listings"][listingId]; + if (list) { + list.show((page - 1) * list.page + 1, list.page); + } +} + +function activateCategory(category) { + // Deactivate existing categories + const activeEls = window.document.querySelectorAll( + ".quarto-listing-category .category.active" + ); + for (const activeEl of activeEls) { + activeEl.classList.remove("active"); + } + + // Activate this category + const categoryEl = window.document.querySelector( + `.quarto-listing-category .category[data-category='${category}'` + ); + if (categoryEl) { + categoryEl.classList.add("active"); + } + + // Filter the listings to this category + filterListingCategory(category); +} + +function filterListingCategory(category) { + const listingIds = Object.keys(window["quarto-listings"]); + for (const listingId of listingIds) { + const list = window["quarto-listings"][listingId]; + if (list) { + if (category === "") { + // resets the filter + list.filter(); + } else { + // filter to this category + list.filter(function (item) { + const itemValues = item.values(); + if (itemValues.categories !== null) { + const categories = itemValues.categories.split(","); + return categories.includes(category); + } else { + return false; + } + }); + } + } + } +} diff --git a/dapla-manual/_quarto.yml b/dapla-manual/_quarto.yml index f7478683..179bb7aa 100644 --- a/dapla-manual/_quarto.yml +++ b/dapla-manual/_quarto.yml @@ -33,6 +33,8 @@ website: href: utviklere/index.qmd - text: Eksempler href: notebooks/index.qmd + - text: "Blogg" + href: blog/index.qmd - text: 'Om Dapla' href: om-dapla.qmd - text: Hjelp diff --git a/dapla-manual/blog/index.qmd b/dapla-manual/blog/index.qmd new file mode 100644 index 00000000..ec1052ef --- /dev/null +++ b/dapla-manual/blog/index.qmd @@ -0,0 +1,16 @@ +--- +title: Dapla-bloggen +subtitle: Stedet der alle i SSB kan dele erfaringer og kunnskap om Dapla +listing: + sort: "date desc" + contents: "posts/*/index.qmd" + sort-ui: false + filter-ui: false + categories: true + feed: false +page-layout: full +title-block-banner: "#e3f1e6" +title-block-banner-color: body +search: false +image: ../images/dapla-favicon.png +--- \ No newline at end of file diff --git a/dapla-manual/blog/posts/2023-01-12-jupyter-cell-embedding/fame.png b/dapla-manual/blog/posts/2023-01-12-jupyter-cell-embedding/fame.png new file mode 100644 index 0000000000000000000000000000000000000000..b9c292fa4bff6c5ff9739b06a99c0cac9a15ed81 GIT binary patch literal 6103 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 E2Tj^-@Bjb+ literal 0 HcmV?d00001 diff --git a/dapla-manual/blog/posts/2023-01-12-jupyter-cell-embedding/index.qmd b/dapla-manual/blog/posts/2023-01-12-jupyter-cell-embedding/index.qmd new file mode 100644 index 00000000..f29da136 --- /dev/null +++ b/dapla-manual/blog/posts/2023-01-12-jupyter-cell-embedding/index.qmd @@ -0,0 +1,95 @@ +--- +title: Fra Fame til Python +subtitle: Python-pakken `fython` lar deg hente ut data fra Fame-databaser for å jobbe med det i Python. +categories: + - Fame + - Python + - Tidsserier +author: + - name: Magnus Kvåle Helliesen + affiliation: + - name: Seksjon for nasjonalregnskap (210) + email: magnus.helliesen@ssb.no +date: "01/12/2024" +date-modified: "01/13/2024" +image: fame.png +image-alt: "Bilde av Fame-logoen" +draft: false +--- + +Mange i SSB har data lagret i Fame som de ønsker å bearbeide med Python og R. Dette er spesielt relevant når man skal flytte statistikkproduksjon til Dapla. `fython` er en Python-pakke som gjør dette på en enkel måte for deg. Den lar deg eksportere data fra Fame med en enkel funksjon, og kan returnere dataene som enten CSV eller Pandas DataFrame. + +## Installasjon + +Pakken ligger på GitHub og kan installeres derfra. I et [ssb-project](../../../statistikkere/jobbe-med-kode.html#opprett-ssb-project) installerer du ved å kjøre følgende kommando: + +```{.bash filename="terminal"} +poetry add git+https://github.com/statisticsnorway/ssb-fame-to-python.git +``` + +Pakken er også ferdiginstallert på serveren der Fame installert: `sl-fame-1.ssb.no`. Dette kan være nyttig i flere sammenhenger som vi kommer inn på senere i innelegget. + +## Bruk av funksjonene + +`fython` har to funksjoner: `fame_to_csv` og `fame_to_df`. Begge disse funksjonene tar inn de samme argumentene og de er listet opp i @tbl-fython-args. + +| Argument | Forklaring | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| databases | List of Fame databases to access (with full path). | +| frequency | Frequency of the data ('a', 'q', 'm'). | +| date_from | Start date for the data in Fame syntax (e.g., '2023:1' for quarterly, '2023' for annual). | +| date_to | End date for the data in Fame syntax (e.g., '2023:1' for quarterly, '2023' for annual). | +| search_string | Query string for fetching specific data.  The search is not case sensitive, and "^" and "?" are wildcards (for exactly one and any number of characters, respectively) | +| decimals | Number of decimal places in the fetched data (default is 10). | +: Forklaring av argumentene i funksjonene til `fython` {#tbl-fython-args} + +La se på noen eksempler. + +### Eksempler + +Dersom vi ønsker å hente alt i `database1.db` og `database2.db` fra **januar 2012** til **desember 2022**, og få det returnert i en DataFrame, kan vi skrive følgende kode: + +```{.python filename="python"} +from fython import fame_to_pandas + +df = fame_to_pandas( + ['sti/til/database1.db', 'sti/til/database2.db', 'm', '2012:1', '2022:12', '?'] + ) +``` +Dersom vi i stedet ønsker å hente alle serier som begynner på **abc**, slutter på **d** etterfulgt av ett vilkårlig tegn, kan vi skrive følgende kode: + +```{.python filename="python"} +from fython import fame_to_pandas + +df = fame_to_pandas( + ['sti/til/database1.db', 'sti/til/database2.db', 'm', '2012:1', '2022:12', 'abc?d^'] + ) +``` + +`?` og `^` er altså jokertegn/wildcards som representerer henholdvis et vilkårlig antall tegn og nøyaktig ett tegn. + +Dersom vi i stedet vil lagre dataene til en csv-fil kan vi skrive + +```{.python filename="python"} +from fython import fame_to_csv + +fame_to_csv( + ['sti/til/database1.db', 'sti/til/database2.db', 'm', '2012:1', '2022:12', 'abc?d^', 'sti/til/csv-fil.csv'] + ) +``` + +## Kjøringer på serveren + +Når du skal bruke `fython` så må du ta hensyn til hvilken server Fame er installert på, og hvilken server du har tenkt til å jobbe på. Fame er som sagt installert på `sl-fame-1.ssb.no`, mens Jupyterlab er installert på `sl-jupyter-p.ssb.no`. Dvs. at hvis du ønsker å bruke `fython` i en notebook i Jupyterlab, så må du [bruke ssh](https://ubiquitous-doodle-n15e62e.pages.github.io/posts/ssh-onprem/) til å koble deg til `sl-fame-1.ssb.no`, og så kjøre koden derfra. Koden din kan skrive en fil til ønsket stammeområdet, som du igjen kan lese inn direkte i Jupyterlab. + +## Automatiserte uttrekk + +Hvis man ønsker at utrekk fra Fame skal skje automatisk på gitte tidspunkter eller intervaller, så kan man ta kontakt med Kundeservice. Fordelen med dette er at man ikke trenger å bruke `ssh` slik som beskrevet over. Man kan lese inn direkte fra stammeområdet. + +## Overføre data til Dapla + +Hvis man ønsker å overføre data fra Fame til Dapla, så kan dette settes opp som en MoveIt-operasjon. For å sette opp en MoveIt-jobb må ma kontakte Kundeservice. Overføring til Dapla forutsetter at man har et Dapla-team, og at man setter opp en synkroniseringjobb med [Transfer Service](../../../statistikkere/transfer-service.html). + + + +