{"id":21874038,"url":"https://github.com/ianjure/average-precipitation-map","last_synced_at":"2025-08-16T09:10:02.887Z","repository":{"id":235944517,"uuid":"791586898","full_name":"ianjure/average-precipitation-map","owner":"ianjure","description":"A 3D data visualization of average precipitation using R.","archived":false,"fork":false,"pushed_at":"2024-04-29T23:12:27.000Z","size":15957,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-21T23:17:25.361Z","etag":null,"topics":["data-visualization","philippines","r"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ianjure.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-25T01:45:18.000Z","updated_at":"2024-08-13T12:53:44.000Z","dependencies_parsed_at":"2024-04-25T03:22:48.112Z","dependency_job_id":"bb2631d3-7d23-4dd8-b1f1-c73e6d0a593a","html_url":"https://github.com/ianjure/average-precipitation-map","commit_stats":null,"previous_names":["ianjure/average-precipitation-map"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ianjure/average-precipitation-map","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianjure%2Faverage-precipitation-map","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianjure%2Faverage-precipitation-map/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianjure%2Faverage-precipitation-map/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianjure%2Faverage-precipitation-map/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ianjure","download_url":"https://codeload.github.com/ianjure/average-precipitation-map/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ianjure%2Faverage-precipitation-map/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270690571,"owners_count":24628915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-16T02:00:11.002Z","response_time":91,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-visualization","philippines","r"],"created_at":"2024-11-28T07:10:44.239Z","updated_at":"2025-08-16T09:10:02.860Z","avatar_url":"https://github.com/ianjure.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"Philippines Average Precipitation Map.png\" width=\"1000\"/\u003e\n\n## About the Project\n\nPrecipitation refers to the amount of water released from clouds in the\nform of rain, freezing rain, sleet, snow, or hail. It is the main way\natmospheric water returns to the surface of the Earth. Since the\nPhilippines is a tropical country that experiences an average of 20\ntyphoons every year, we want to visualize how each province is affected\nby these precipitations.\n\n## About the Data\n\nMulti-Source Weighted-Ensemble Precipitation (MSWEP) is a global\nprecipitation dataset with a 3‑hourly 0.1° resolution available from\n1979 to \\~3 hours from real-time. The dataset is unique in that it\nmerges gauge, satellite, and reanalysis data to obtain the highest\nquality precipitation estimates at every location.\n\n# How to Create a 3D Average Precipitation Map in R\n\n#### **1. Install and Load Required Packages**:\n\nYou need to install the necessary packages. Run the code chunk to\ninstall them, it might require restarting the R-session several times.\nThen load the required libraries.\n\n```{r message=FALSE}\nif(\n    !require(\"pacman\")\n){\n    install.packages(\"pacman\")\n}\n\npacman::p_load(\n    pRecipe,\n    giscoR,\n    terra,\n    tidyverse,\n    ggpubr,\n    rayshader,\n    sf,\n    classInt,\n    magick\n)\n```\n\nThis section checks if the Pacman package is installed, and if not,\ninstalls it. Then it loads several packages using the *p_load()*\nfunction.\n\n#### **2. Load and Rasterize the Data**:\n\nYou'll need to select a country of choice, then download and rasterize\nthe precipitation data.\n\n```{r message=FALSE}\ncountry_sf \u003c- giscoR::gisco_get_countries(\n    country = \"PH\", #Change Country Code\n    resolution = \"1\"\n)\n\npRecipe::download_data(\n    dataset = \"mswep\",\n    path = getwd(),\n    domain = \"raw\",\n    timestep = \"yearly\"\n)\n\nmswep_data \u003c- terra::rast(\n    \"mswep_tp_mm_global_197902_202301_025_yearly.nc\"\n) |\u003e\nterra::crop(\n    country_sf\n)\n\nterra::plot(mswep_data[[1]])\nplot(sf::st_geometry(country_sf), add = TRUE)\n```\n\nThis section retrieves the spatial data for the Philippines (the country\ncode is based on ISO 3166-2) at a resolution of 1 using the Giscor\npackage. Then it downloads precipitation data from the MSWEP dataset,\nusing the *download_data()* function, to the current working directory.\nThen it will rasterize the data, crop it to the extent of the country,\nand plot the data. The country codes can be found at:\n\u003chttps://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes\u003e\n\n#### **3. Format the Data**:\n\nTo visualize the precipitation over time you need to format the data\ninto a tidy form suitable for plotting.\n\n```{r}\nnames(mswep_data) \u003c- 1979:2023\n\nmswep_df \u003c- mswep_data |\u003e\n    as.data.frame(xy = TRUE) |\u003e\n    tidyr::pivot_longer(\n        !c(\"x\", \"y\"),\n        names_to = \"year\",\n        values_to = \"precipitation\"\n    ) |\u003e\n    dplyr::filter(year != 2023)\n\nhead(mswep_df)\n```\n\nThis section uses the *names()* function to set the names of the objects\nto years, starting from 1979 to 2023. Then it transforms the rasterized\ndata into a data frame for proper plotting and filters the year 2023\nsince its data is still incomplete.\n\n#### **4. Calculate Average Precipitation:**\n\nSince the goal is to visualize the average precipitation, you need to\nfirst calculate the mean precipitation value of every coordinates from\n1979 to 2022.\n\n```{r message=FALSE}\nmswep_average_df \u003c- mswep_df |\u003e\n    dplyr::group_by(\n        x, y, .drop = FALSE\n    ) |\u003e\n    dplyr::summarise(\n        mean = mean(precipitation)\n    )\n\nhead(mswep_average_df)\n```\n\nThis section calculates the average precipitation for each location,\nthen shows these average values using the *head()* function.\n\n#### **5. Create Theme and Define Color Palette**:\n\nYou'll need to define a custom theme for ggplot, calculate the legend\nbreaks, and determine the color palette for the project based on the\nprecipitation data.\n\n```{r}\ntheme_precipitation \u003c- function(){\n    theme_minimal() +\n    theme(\n        axis.line = element_blank(),\n        axis.title.x = element_blank(),\n        axis.title.y = element_blank(),\n        axis.text.x = element_blank(),\n        axis.text.y = element_blank(),\n        legend.position = \"left\",\n        legend.title = element_text(\n            size = 18, color = \"#005E5E\"\n        ),\n        legend.text = element_text(\n            size = 16, color = \"#005E5E\"\n        ),\n        panel.grid.major = element_line(\n            color = NA\n        ),\n        panel.grid.minor = element_line(\n            color = NA\n        ),\n        plot.background = element_rect(\n            fill = NA, color = NA\n        ),\n        legend.background = element_rect(\n            fill = \"white\", color = NA\n        ),\n        panel.border = element_rect(\n            fill = NA, color = NA\n        ),\n        plot.margin = unit(\n            c(\n                t = 0, r = 0,\n                b = 0, l = 0\n            ), \"lines\"\n        )\n    )\n}\n\nbreaks \u003c- classInt::classIntervals(\n    mswep_average_df$mean,\n    n = 5,\n    style = \"equal\"\n)$brks\n\ncolors \u003c- hcl.colors(\n    n = length(breaks),\n    palette = \"Batlow\", #Choose Color Palette\n    rev = TRUE\n)\n```\n\nThis section creates a function that customizes a ggplot theme. It also\ndefines the breaks and colors that will be used for the legend. The\npalettes can be found at:\n\u003chttps://colorspace.r-forge.r-project.org/articles/hcl_palettes.html\u003e\n\n#### **6. Check and Plot the Data**:\n\nVisualize the calculated average precipitation data.\n\n```{r}\nmap \u003c- ggplot(\n    data = mswep_average_df\n) +\ngeom_raster(\n    aes(\n        x = x,\n        y = y,\n        fill = mean\n    )\n) +\ngeom_contour(\n    aes(\n       x = x,\n       y = y,\n       z = mean \n    ), color = \"white\"\n) +\ngeom_sf(\n    data = country_sf,\n    fill = \"transparent\",\n    color = \"#323232\",\n    linewidth = 0.5\n) +\nscale_fill_gradientn(\n    name = \"mm\",\n    colors = colors,\n    breaks = breaks, \n    labels = round(breaks, 0), # use round(breaks, 0)\n    limits = c(\n        min(mswep_average_df$mean),\n        max(mswep_average_df$mean)\n    )\n) +\ntheme_precipitation() + theme(legend.position = \"none\")\n\nmap #Show Plot\n```\n\nThis section uses ggplot's functionality to show the average\nprecipitation data.\n\n#### **7. Save Legend as Image**:\n\nExport the plot's legend as an image using ggpubr.\n\n```{r eval=FALSE}\nlgnd \u003c- ggplot(\n    data = mswep_average_df\n) +\ngeom_raster(\n    aes(\n        x = x,\n        y = y,\n        fill = mean\n    )\n) +\ngeom_contour(\n    aes(\n       x = x,\n       y = y,\n       z = mean \n    ), color = \"white\"\n) +\ngeom_sf(\n    data = country_sf,\n    fill = \"transparent\",\n    color = \"#323232\",\n    linewidth = 0.5\n) +\nscale_fill_gradientn(\n    name = \"mm\",\n    colors = colors,\n    breaks = breaks, \n    labels = round(breaks, 0),\n    limits = c(\n        min(mswep_average_df$mean),\n        max(mswep_average_df$mean)\n    )\n) +\nguides(\n    fill = guide_colourbar(\n        direction = \"vertical\",\n        barheight = unit(80, \"mm\"),\n        barwidth = unit(8, \"mm\"),\n        title.position = \"bottom\",\n        label.position = \"right\",\n        title.hjust = 0,\n        label.hjust = .5,\n        title.vjust = 0,\n        ncol = 1,\n        byrow = FALSE\n    )\n) +\ntheme_precipitation()\n\nlegend \u003c- get_legend(lgnd)\nas_ggplot(legend)\nggsave(\"Legend.png\", path=getwd(),width=1900, height=1900, limitsize = FALSE, units=\"px\", bg=\"white\")\n```\n\nThis section will extract the legend using the *get_legend()* function\nfrom ggpubr, then it will plot and save the legend as an image using\nggplot's functions.\n\n#### **8. Render 3D Map**:\n\nUse Rayshader to create a 3D representation of the average\nprecipitation.\n\n```{r message=FALSE, eval=FALSE}\nrayshader::plot_gg(\n    ggobj = map,\n    width = 7,\n    height = 7,\n    scale = 250,\n    solid = FALSE,\n    shadow = TRUE,\n    shadowcolor = \"white\",\n    shadowwidth = 0,\n    shadow_intensity = 1,\n    windowsize = c(1049,1569),\n)\n```\n\n```{r message=FALSE, eval=FALSE}\nrayshader::render_camera(\n    phi = 55,\n    theta = 15,\n    zoom = .58\n)\n```\n\nThis section converts the 2D map created in step 6 into a 3D contour map\nusing the rayshader package.\n\n#### **9. Render in High-Quality and Save Image**:\n\nDownload an HDRI file and render a high-quality image of the 3D map.\n\n```{r eval=FALSE}\nhdri_url \u003c- \"https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/4k/air_museum_playground_4k.hdr\"\n\nhdri_file \u003c- basename(hdri_url)\n\ndownload.file(\n    url = hdri_url,\n    destfile = hdri_file,\n    mode = \"wb\"\n)\n\nrayshader::render_highquality(\n    filename = \"PH_3D_Render.png\",\n    preview = TRUE,\n    interactive = FALSE,\n    parallel = TRUE,\n    light = TRUE,\n    environment_light = \"air_museum_playground_4k.hdr\",\n    rotate_env = 90,\n    width = 3138,\n    height = 4437\n)\n```\n\nThis section will download a High Dynamic Range Image (HDRI) file, then\nuses rayshader's *render_highquality()* function to generate a\nhigh-quality PNG image of the 3D contour map with added lighting\neffects.\n\n#### **10. Annotate the Image:**\n\nYou can add names and more details about your generated visualization.\n\n```{r eval=FALSE, tidy=TRUE}\npop_raster \u003c- image_read(\"PH_3D_Render.png\")\n\npop_raster %\u003e%\n  image_annotate(\"PHILIPPINES\",\n                 gravity = \"northeast\",\n                 location = \"+90+60\",\n                 kerning = 0,\n                 color = \"#005E5E\",\n                 size = 330,\n                 weight = 750,\n  ) %\u003e%\n  image_annotate(\"AVERAGE PRECIPITATION MAP (1979-2022)\",\n                 gravity = \"northeast\",\n                 location = \"+110+410\",\n                 color = \"#005E5E\",\n                 size = 85,\n                 weight = 550,\n                 boxcolor = \"white\"\n  ) %\u003e%\n  image_annotate(\"Surigao del Sur\",\n                 gravity = \"southeast\",\n                 location = \"+120+1000\",\n                 color = \"#005E5E\",\n                 size = 85,\n                 weight = 500,\n  ) %\u003e%\n  image_annotate(\"Eastern\\nSamar\",\n                 gravity = \"southeast\",\n                 location = \"+120+1900\",\n                 color = \"#005E5E\",\n                 size = 85,\n                 weight = 500,\n  ) %\u003e%\n  image_annotate(\"Sulu\",\n                 gravity = \"southwest\",\n                 location = \"+500+400\",\n                 color = \"#005E5E\",\n                 size = 85,\n                 weight = 500,\n  ) %\u003e%\n  image_annotate(\"Palawan\",\n                 gravity = \"northwest\",\n                 location = \"+120+2200\",\n                 color = \"#005E5E\",\n                 size = 85,\n                 weight = 500,\n  ) %\u003e%\n  image_annotate(\"Visualization by: Ayad, Cariño, Macalisang and Santos\\n\n                 Data: Multi-Source Weighted-Ensemble Precipitation (MSWEP) 1979-2022\",\n                 gravity = \"southwest\",\n                 location = \"+75+65\",\n                 color = \"#005E5E\",\n                 size = 68,\n  ) %\u003e%\n  image_write(\"PH_3D_Render_Annotated.png\", format = \"png\", quality = 1000)\n\n\nimage \u003c- image_read(\"PH_3D_Render_Annotated.png\")\nget_legend \u003c- image_read(\"Legend.png\")\nlegend \u003c- image_trim(get_legend)\noutput \u003c- image_composite(image, legend, offset = \"+195+151\")\n\nget_logo \u003c- image_read(\"ds_logo.png\")\nlogo_scale \u003c- image_scale(get_logo, \"550\")\noutput_final \u003c- image_composite(output, logo_scale, gravity = \"southeast\", offset = \"+100+50\")\n\nimage_write(output_final, \"PH_3D_Average_Precipitation_Map.png\", format = \"png\", quality = 1000)\n```\n\nThis section will add the annotations, other details and the exported\nlegend image to the 3D-rendered image using magick. Then it will export\nthe final output of the project.\n\n## Analysis\n\nAs shown by the legend breaks, the average precipitation of the country\ngathered from 1979 to 2022 ranges from 1359 to 4279 millimeters.\n\nUsing the visualization, we can infer that the province of Surigao del\nSur has the highest average precipitation, varying from 3695 to 4279\nmillimeters. It is then followed by the Eastern Samar province, with an\naverage precipitation between 3111 and 3695 millimeters. Furthermore,\nPalawan and Sulu are some of the provinces that show low average\nprecipitation. And among the three major island groups, Mindanao has the\nhighest average precipitation, where more than 50% of the island's\nprovinces show medium to high level average.\n\nWe can also suggest that these results can be due to a province's\ngeographical location. Provinces with high average precipitation tend to\nbe in the eastern part of the country, which is adjacent to the Pacific\nOcean, where most tropical cyclones are more likely to form. It can also\nbe due to a province's land area, since provinces with low average\nprecipitation are typically islands with smaller land areas.\n\n## Project Inspiration\n\nThis project is inspired by https://github.com/milos-agathon/precipitation-maps\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fianjure%2Faverage-precipitation-map","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fianjure%2Faverage-precipitation-map","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fianjure%2Faverage-precipitation-map/lists"}