Jobbe med data
Når vi oppretter et dapla-team så får vi tildelt et eget området for lagring av data. For å kunne lese og skrive data fra Jupyter til disse områdene må vi autentisere oss, siden Jupyter og lagringsområdet er to separate sikkerhetsoner.
Figur 1 viser dette klarer skillet mellom hvor vi koder og hvor dataene ligger på Dapla1. I dette kapitlet beskriver vi nærmere hvordan du kan jobbe med dataene dine på Dapla.
SSB-biblioteker
For å gjøre det enklere å jobbe data på tvers av Jupyter og lagringsområdet er det laget noen egne SSB-utviklede biblioteker for å gjøre vanlige operasjoner mot lagringsområdet. Siden både R og Python skal brukes på Dapla, så er det laget to biblioteker, en for hver av disse språkene. fellesr er biblioteket for R, og dapla-toolbelt er biblioteket for Python.
dapla-toolbelt
dapla-toolbelt er en en pakke som lar deg enkelt lese og skrive til lagringsområdet uten å måtte autentifisere deg manuelt. Den har en Pandas-aktig syntaks som forhåpentlig er gjenkjennbar for de fleste. Pakken er installert i alle Python-kernels på Dapla, så du trenger ikke å installere den selv hvis du åpner en notebook med Python3 for eksempel. For å importere hele biblioteket i en notebook skriver du bare
import dapla as dp
dapla-toolbelt bruker en pakke som heter gcsfs for å kommunisere med lagringsområdet. gcsfs er en pakke som lar deg bruke Google Cloud Storage (GCS) som om det var en filsystem. Det betyr at du kan bruke samme syntaks som du bruker for å lese og skrive til filer på din egen maskin. Du kan lese mulighetene i gcsfs her. Et eksempel på hvordan de to pakkene kan brukes sammen ser du her:
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
# Example of how you can use gcsfs and dapla-toolbelt together
"gs://my-bucket/my-folder/") fs.touch(
I koden over brukte jeg kommandoen touch
fra gcsfs og FileClient
fra dapla-toolbelt for å opprette en mappe i lagringsområdet.
I kapitlene under finner du konkrete eksempler på hvordan du kan bruke dapla-toolbelt til å jobbe med data i SSBs lagringsområdet.
fellesr
R-pakken fellesr er under utvikling og gir mye av den samme funksjonaliteten som dapla-toolbelt gir for Python. I tillegg til å kunne lese og skrive til lagringsområdet på Dapla, så har fellesr også funksjoner for å jobbe med metadata på Dapla.
fellesr er installert på Dapla og funksjoner kan benyttes ved:
library(fellesr)
Hvis du benytte en renv miljø, må pakken installeres en gang. Dette kan gjøres ved:
::install("statisticsnorway/fellesr") renv
Vanlige operasjoner
I denne delen viser vi hvordan man gjør veldig vanlige operasjoner når man koder et produksonsløp for en statistikk. Flere eksempler på nyttige systemkommandoer finner du her.
Liste ut innhold i mappe
Det finnes et område som alle SSB-ansatte har lese- og skrivetilgang til. Det er
gs://ssb-prod-dapla-felles-data-delt/ i prod-miljøet på Dapla, og
gs://ssb-staging-dapla-felles-data-delt/ i staging-miljøet. Eksemplene under bruker førstnevnte i koden, slik at alle kan kjøre koden selv.
Kode-eksemplene finnes for både R og Python, og du kan velge hvilken du skal se ved å trykke på den arkfanen du er interessert i.
Å liste ut innhold i et gitt mappe på Dapla er ganske enkelt. Under ser du hvordan du kan liste ut innholdet i følgende mappe:
gs://ssb-prod-dapla-felles-data-delt/felles/veiledning/python/eksempler/purchases
Vi bruker modulen FileClient
fra dapla-toolbelt for å liste ut innholdet i en mappe.
from dapla import FileClient
# Set path to folder
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
folder
f"{bucket}/{folder}") FileClient.ls(
Med kommandoen over får du listet ut alle filnavn i mappen. Hvis du vil ha mer informasjon om filene så kan du bruke ls
-kommandoen med detail = True
, som under:
f"{bucket}/{folder}", detail = True) FileClient.ls(
Syntaksen med ls
er veldig lik det man kjenner fra en Linux-terminal. Men når vi bruker detail = True
blir metadata om filene returnert som en Python-liste med dictionaries. Det kan være svært nyttig når du f.eks. trenger å vite dato og tidspunkt for når en fil ble opprettet, eller når den sist ble oppdatert.
# Loading functions into notebook
library(fellesr)
# Path to folder
<- "ssb-prod-dapla-felles-data-delt/"
bucket <- "felles/veiledning/python/eksempler/purchases"
folder
# List files in folder
list.files(paste0(bucket, folder))
Merknad: Når du spesifisere bøtter i R, trenger du ikke “gs://” foran.
Skrive ut filer
Å skrive filer til et lagringsområde på Dapla er også ganske enkelt. Det ligner mye på den syntaksen vi er kjent med fra vanlige R- og Python-pakker, med noen små unntak.
Parquet
Under lager vi en dataframe i en notebook og skriver den ut til en parquet-fil.
Når vi leser en Parquet-fil med dapla-toolbelt så bruker den pyarrow i bakgrunnen. Dette er en av de raskeste måtene å lese og skrive Parquet-filer på.
import dapla as dp
import pandas as pd
import numpy as np
# Set path to folder
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
folder
# Create pandas dataframe
= pd.DataFrame(np.random.randn(10, 5),
purchases =["A", "B", "C", "D", "E"])
columns
# Write pandas dataframe as parquet to GCS bucket
= purchases,
dp.write_pandas(df = f"{bucket}/{folder}/data.parquet",
gcs_path = "parquet",) file_format
Når vi kalte write_pandas
over så spesifiserte vi at filformatet skulle være parquet
. Dette er default, så vi kunne også ha skrevet det slik:
= purchases,
dp.write_pandas(df = f"{bucket}/{folder}/data.parquet") gcs_path
Men for de andre filformatene må vi altså spesifisere dette.
Når vi jobber med Parquet-fil i R, bruker vi pakken arrow. Dette er en del av fellesr pakken så du trenger kun å kalle inn dette. Pakken inneholder funksjonen write_SSB
som kan brukes til å skrive data til bøtte på Dapla.
library(fellesr)
# Set stien til hvor data skal lagres
<- "ssb-prod-dapla-felles-data-delt"
bucket <- "felles/veiledning/r/eksempler/purchases"
folder
# Lage en eksempel dataframe
= data.frame(A = runif(10), B= runif(10), C=runif(10))
purchases
# Skrive data til bøttet som en parquet
write_SSB(purchases, file.path(bucket, folder, "purchases.parquet"))
Merknad: Når du spesifisere bøtter i R, trenger du ikke “gs://” foran.
Tekstfiler
Noen ganger ønsker vi å lagre data i andre formatter slik som CSV, JSON og XML.
dapla-toolbelt kan skrive ut json, csv og posisjonsfiler (fixed-width-files/fwf) til lagringsområdet. Måten den gjør det på er å bruke Pandas sine funksjoner read_json
, read_csv
, read_fwf
under panseret. Dette kan være nyttig å vite for skjønne hvordan dapla-toolbelt håndterer ulike strukturer i (spesielt hierarkiske) tekstfiler. Under ser du hvordan du kan skrive ut en dataframe til en json-fil.
import numpy as np
import pandas as pd
from dapla import FileClient
# Set path to folder
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
folder
# Create a dataframe with Pandas
= pd.DataFrame(np.random.randn(10, 5), columns=["A", "B", "C", "D", "E"])
df
# Save dataframe as json with dapla-toolbelt
= df,
dp.write_pandas(df = f"{bucket}/{folder}/test.json",
gcs_path = "json") file_format
Som vi ser at syntaksen over så kunne vi skrevet ut til noe annet enn json ved å endre verdien i argumentet file_format
.
Pakken fellesr kan også brukes til å skrive andre type filer, for eksempel csv, til bøtter. Dette gjøres med funksjonen write_SSB
og spesifisere ønsket filtype i filnavn.
Først kaller vi biblioteket og lage noe test data ved:
library(fellesr)
# Set stien til hvor data skal lagres
<- "ssb-prod-dapla-felles-data-delt"
bucket <- "felles/veiledning/r/eksempler/purchases"
folder
# Lage en eksempel dataframe
= data.frame(A = runif(10), B= runif(10), C=runif(10))
purchases
# Skrive til csv
write_SSB(purchases, file.path(bucket, folder, "purchases.csv")
xlsx
Det er ikke anbefalt å bruke xlsx-formatet, men her ser du hvordan det kan skrives ut. Mer kommer.
import pandas as pd
from dapla import AuthClient
# Henter token for å kunne lese fra Dapla
= AuthClient.fetch_google_credentials()
token
# Filsti
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
folder
f"{bucket}/{folder}/test.xlsx",
df.to_excel(={"token": token}) storage_options
Kommer snart
Lese inn filer
Under finner du eksempler på hvordan du kan lese inn data til en Jupyter Notebooks på Dapla.
Parquet
import dapla as dp
# Set path to folder
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
folder
# Read path into pandas dataframe
= f"{bucket}/{folder}/data.parquet",
dp.read_pandas(gcs_path= "parquet",
file_format = None,) columns
Som vi så med write_pandas
så er file_format
default satt til parquet
, og default for columns = None
, så vi kunne også ha skrevet det slik:
= f"{bucket}/{folder}/data.parquet") dp.read_pandas(gcs_path
columns
-argumentet er en liste med kolonnenavn som vi ønsker å lese inn. Hvis vi ikke spesifiserer noen kolonner så vil alle kolonnene leses inn.
Pakken fellesr kan brukes til å lese inn data. Funksjonen read_SSB()
kan lese inn filer i flere format inkluderende parquet.
Her er et eksempel av å lese inn parquet fil “1987”.
library(fellesr)
<- "ssb-prod-dapla-felles-data-delt"
bucket <- "R_smoke_test"
folder
<- read_SSB(file.path(bucket, folder, "1987.parquet")) dt_1987
Vi kan også filtrere hvilke variabel vi ønsker å lese inn ved å spesifisere parameter col_select
. For eksempel:
<- read_SSB(file.path(bucket, folder, "1987.parquet"),
dt_1987 col_select = c("Year", "Month"))
Innlesning av parquet som er kartdata finner du her: Lese kartdata
Tekstfiler
Kommer mer snart. Python-koden under bygger på eksempelet over.
import dapla as dp
# Path to write to
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
folder
# Read in json-file from dapla-storage
= dp.read_pandas(gcs_path = f"{bucket}/{folder}/test3.json",
df = "json") file_format
Funksjonen read_SSB()
kan lese inn flere type av fil-format, slik som csv og json. Du trenger ikke å endre koden, kun spesifisere hele filnavn.
Først kaller vi inn biblioteket fellesr og spesifisere bøtte/mappen:
library(fellesr)
# Filsti
<- "ssb-prod-dapla-felles-data-delt"
bucket <- "R_smoke_test"
folder
# Lese inn CSV-fil
<- read_SSB(file.path(bucket, folder, "1987.csv")) dt_1987
For å lese inn en json-fil kan skrive følgende:
<- read_SSB(file.path(bucket, folder, "1987.json")) dt_1987
xlsx
import pandas as pd
from dapla import AuthClient
# Hent token
= AuthClient.fetch_google_credentials()
token
# Les inn fil
= pd.read_excel("gs://ssb-prod-arbmark-skjema-data-produkt/test_gcp.xlsx",
df ={"token": token}) storage_options
Kommer snart
SAS
Her er et eksempel på hvordan man leser inn en sas7bdat-fil på Dapla som har blitt generert i prodsonen.
import pandas as pd
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
= "gs://ssb-prod-dapla-felles-data-delt/felles/veiledning/sas/statbank_ledstill.sas7bdat"
sti
with fs.open(sti) as sas:
= pd.read_sas(sas, format="sas7bdat", encoding="latin1") df
I produksjon sone (på bakken) kan R-pakken haven benyttes for å lese inn .sas7bdat filer. Dette er ikke implementert i fellesr enda for lesing fra Dapla bøtte.
Mer om dette kommer.
Slette filer
Å slette filer fra lagringsområdet kan gjøres på flere måter. I kapitlet om sletting av data viste vi hvordan man gjør det med pek-og-klikk i Google Cloud Console. Under ser du hvordan du kan slette filer med dapla-toolbelt og gcsfs eller fellesr.
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
folder
f"{bucket}/{from_folder}/df.json") fs.rm(
Funksjonen gc_delete_object
kan brukes til å slette data på lagringsområdet.
library(fellesr)
<- "ssb-prod-dapla-felles-data-delt"
bucket <- "felles/veiledning/r/eksempler/purchases"
folder
gcs_delete_object(file.path(bucket, folder, "purchases.parquet"))
Kopiere filer
Å kopiere filer mellom mapper på et Linux-filsystem innebærer som regel bruke cp
-kommandoen. På Dapla er det ikke så mye forskjell. Vi bruker en ligende tilnærming nå vi skal kopiere mellom bøtter eller mapper på lagringsområdet til SSB. Under ser du hvordan du kan kopiere en fil fra en mappe til en annen.
La oss begynne med et eksempel der vi kopierer en fil fra en mappe til en annen i samme bøtte.
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
# Path to folders
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
from_folder = "felles/veiledning/python/eksempler"
to_folder
# Copy file
f"{bucket}/{from_folder}/data.parquet",
fs.cp(f"{bucket}/{to_folder}/data_copy.parquet")
Det også fungere for å kopiere filer mellom bøtter.
Et annet scenario vi ofte vil støte på er at vi ønsker å kopiere en fil fra vårt Jupyter-filsystem til en mappe på lagringsområdet. Her kan vi bruke fs.put
-metoden.
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
# Create a new file in your home directory called test.txt
with open('/home/jovyan/test.txt', 'w') as f:
'Create a new text file!')
f.write(
#Path to folder
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler"
folder
# Copy file from local to remote file system
=f"/home/jovyan/test.txt", rpath=f"{bucket}/{folder}/test.txt") fs.put(lpath
Ønsker vi å kopiere en hel mappe fra lagringsområdet til Jupyter-filsystemet, kan vi bruke fs.get
-metoden, med opsjonen recursive=True.
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
# Copy file
<from_bucket>,
fs.get("/home/jovyan/sesongjustering/",
=True) recursive
Kommer snart
Flytte filer
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler/purchases"
from_folder = "felles/veiledning/python/eksempler"
to_folder
f"{bucket}/{from_folder}/data.parquet", f"{bucket}/{to_folder}/data.parquet") fs.mv(
Kommer snart
Opprette mapper
Selv om bøtter ikke har mapper med en hierarkisk struktur slik man er kjent med fra klassike filsystemer, så kan man opprette det som ser ut som mapper i objektnavnet. I realiteten blir bare /
oppfattet som en del av navnet på objektet. Skulle du likevel ønske å opprette dette så kan du gjøre det følgende måte:
from dapla import FileClient
= FileClient.get_gcs_file_system()
fs
#Path to folder
= "gs://ssb-prod-dapla-felles-data-delt"
bucket = "felles/veiledning/python/eksempler"
folder
# Create folder
f"{bucket}/{folder}/testmappe/") fs.touch(
Kommer snart
Fotnoter
I de tidligere systemene på bakken så var det ikke nødvendig med autentisering mellom kodemiljø og datalagringen↩︎