R

Dplyr – manipulation of data frame

In this post, we will introduce the library dplyr, which allows you to easily manipulate variables of type data frame. For our example, we will use the list of geodetic surface fields that you can download as part of open data here.

Let’s initialize the library:

library(dplyr)

Let’s load the data:

dt = readr::read_csv("d:/GIS_in_R/powierzchnie.csv")

First we will use the filter function, which allows us to select rows that meet a certain criterion. In our case, these will be districts for which TERYT has 5 characters:

dt %›% filter(nchar(TERYT) == 5)

As a result we have:

# A tibble: 380 x 3
   TERYT `Nazwa jednostki`     `Powierzchnia [ha]`
   ‹chr› ‹chr›                               ‹dbl›
 1 02 01 Powiat bolesławiecki               130351
 2 02 02 Powiat dzierżoniowski               47851
 3 02 03 Powiat głogowski                    44327
 4 02 04 Powiat górowski                     73827
 5 02 05 Powiat jaworski                     58155
 6 02 06 Powiat jeleniogórski                62714
 7 02 07 Powiat kamiennogórski               39569
 8 02 08 Powiat kłodzki                     164330
 9 02 09 Powiat legnicki                     74408
10 02 10 Powiat lubański                     42830
# ... with 370 more rows

Let’s add the mutate function to our previous line of code, which will allow us to compute a new value (column). We will determine the TERYT of the county from the TERYT of the province (TERYT_woj) using the substr function:

dt %›% filter(nchar(TERYT) == 5) %›% 
mutate(TERYT_woj = substr(TERYT,0,2))

As a result we have:

# A tibble: 380 x 4
   TERYT `Nazwa jednostki`     `Powierzchnia [ha]` TERYT_woj
   ‹chr› ‹chr›                               ‹dbl› ‹chr›    
 1 02 01 Powiat bolesławiecki               130351 02       
 2 02 02 Powiat dzierżoniowski               47851 02       
 3 02 03 Powiat głogowski                    44327 02       
 4 02 04 Powiat górowski                     73827 02       
 5 02 05 Powiat jaworski                     58155 02       
 6 02 06 Powiat jeleniogórski                62714 02       
 7 02 07 Powiat kamiennogórski               39569 02       
 8 02 08 Powiat kłodzki                     164330 02       
 9 02 09 Powiat legnicki                     74408 02       
10 02 10 Powiat lubański                     42830 02       
# ... with 370 more rows

We use the select function to select the columns we are interested in:

dt %›% select(TERYT,'Nazwa jednostki')

And we have:

# A tibble: 4,201 x 2
   TERYT      `Nazwa jednostki`            
   ‹chr›      ‹chr›                        
 1 00         POLSKA                       
 2 02         WOJ. DOLNOŚLĄSKIE            
 3 02 01      Powiat bolesławiecki         
 4 02 01 01 1 Bolesławiec                  
 5 02 01 02 2 Bolesławiec                  
 6 02 01 03 2 Gromadka                     
 7 02 01 04 3 Nowogrodziec                 
 8 02 01 04 4 Nowogrodziec - miasto        
 9 02 01 04 5 Nowogrodziec - obszar wiejski
10 02 01 05 2 Osiecznica                   
# ... with 4,191 more rows

We will use the select we did earlier to add the names of the provinces to our counties, using left_join from the join function group:

dt %›% filter(nchar(TERYT) == 5) %›% 
mutate(TERYT_woj = substr(TERYT,0,2)) %›% 
left_join(dt %›% select(TERYT,'Nazwa jednostki'), by = c("TERYT_woj" = "TERYT"))

The finished table looks like this:

# A tibble: 380 x 5
   TERYT `Nazwa jednostki.x`   `Powierzchnia [ha]` TERYT_woj `Nazwa jednostki.y`
   ‹chr› ‹chr›                               ‹dbl› ‹chr›     ‹chr›              
 1 02 01 Powiat bolesławiecki               130351 02        WOJ. DOLNOŚLĄSKIE  
 2 02 02 Powiat dzierżoniowski               47851 02        WOJ. DOLNOŚLĄSKIE  
 3 02 03 Powiat głogowski                    44327 02        WOJ. DOLNOŚLĄSKIE  
 4 02 04 Powiat górowski                     73827 02        WOJ. DOLNOŚLĄSKIE  
 5 02 05 Powiat jaworski                     58155 02        WOJ. DOLNOŚLĄSKIE  
 6 02 06 Powiat jeleniogórski                62714 02        WOJ. DOLNOŚLĄSKIE  
 7 02 07 Powiat kamiennogórski               39569 02        WOJ. DOLNOŚLĄSKIE  
 8 02 08 Powiat kłodzki                     164330 02        WOJ. DOLNOŚLĄSKIE  
 9 02 09 Powiat legnicki                     74408 02        WOJ. DOLNOŚLĄSKIE  
10 02 10 Powiat lubański                     42830 02        WOJ. DOLNOŚLĄSKIE  
# ... with 370 more rows

Finally, in our long code, we select only the columns of interest in the resulting table (TERYT, unit name, area, and province name). We will give them new names (TERYT, Nazwa, Pow, Woj). The result will be stored in the variable dt:

dt = dt %›% filter(nchar(TERYT) == 5) %›% 
mutate(TERYT_woj = substr(TERYT,0,2)) %›% 
left_join(dt %›% select(TERYT,'Nazwa jednostki'), by = c("TERYT_woj" = "TERYT")) %›%
select(TERYT,Nazwa = `Nazwa jednostki.x`,Pow = `Powierzchnia [ha]`,Woj = `Nazwa jednostki.y`)

The variable dt should contain this data:

# A tibble: 380 x 4
   TERYT Nazwa                    Pow Woj              
   ‹chr› ‹chr›                  ‹dbl› <chr›            
 1 02 01 Powiat bolesławiecki  130351 WOJ. DOLNOŚLĄSKIE
 2 02 02 Powiat dzierżoniowski  47851 WOJ. DOLNOŚLĄSKIE
 3 02 03 Powiat głogowski       44327 WOJ. DOLNOŚLĄSKIE
 4 02 04 Powiat górowski        73827 WOJ. DOLNOŚLĄSKIE
 5 02 05 Powiat jaworski        58155 WOJ. DOLNOŚLĄSKIE
 6 02 06 Powiat jeleniogórski   62714 WOJ. DOLNOŚLĄSKIE
 7 02 07 Powiat kamiennogórski  39569 WOJ. DOLNOŚLĄSKIE
 8 02 08 Powiat kłodzki        164330 WOJ. DOLNOŚLĄSKIE
 9 02 09 Powiat legnicki        74408 WOJ. DOLNOŚLĄSKIE
10 02 10 Powiat lubański        42830 WOJ. DOLNOŚLĄSKIE
# ... with 370 more rows

For the created table we will calculate the minimum, average and maximum area of the districts using the summarize function:

dt %›% summarise(min = min(Pow), avg = mean(Pow), max = max(Pow))
# A tibble: 1 x 3
    min    avg    max
  ‹dbl›  ‹dbl›  ‹dbl›
1  1331 82291. 297644

If we want to calculate these values for provinces, our row should be completed with the function group_by:

dt %›% group_by(Woj) %›% 
summarise(min = min(Pow), avg = mean(Pow), max = max(Pow))
# A tibble: 16 x 4
   Woj                        min     avg    max
   ‹chr›                    ‹dbl›   ‹dbl›  ‹dbl›
 1 WOJ. DOLNOŚLĄSKIE         5629  66489  164330
 2 WOJ. KUJAWSKO-POMORSKIE   5776  78136. 147418
 3 WOJ. LUBELSKIE            3034 104677. 275426
 4 WOJ. LUBUSKIE             8572  99914. 139278
 5 WOJ. ŁÓDZKIE              3460  75912. 149083
 6 WOJ. MAŁOPOLSKIE          5758  69013. 154980
 7 WOJ. MAZOWIECKIE          3186  84663. 209355
 8 WOJ. OPOLSKIE            14888  78432. 153430
 9 WOJ. PODKARPACKIE         4472  71383. 130837
10 WOJ. PODLASKIE            3267 118747. 297644
11 WOJ. POMORSKIE            1728  91618. 230424
12 WOJ. ŚLĄSKIE              1331  34259. 152205
13 WOJ. ŚWIĘTOKRZYSKIE      10965  83646. 224607
14 WOJ. WARMIŃSKO-MAZURSKIE  7982 115112. 283802
15 WOJ. WIELKOPOLSKIE        3186  85219. 189988
16 WOJ. ZACHODNIOPOMORSKIE   9834 109070. 186911

Let’s add the number of districts:

dt %›% group_by(Woj) %›% 
summarise(nr = length(Pow), min = min(Pow), avg = mean(Pow), max = max(Pow))
# A tibble: 16 x 5
   Woj                         nr   min     avg    max
   ‹chr›                    ‹int› ‹dbl›   ‹dbl›  ‹dbl›
 1 WOJ. DOLNOŚLĄSKIE           30  5629  66489  164330
 2 WOJ. KUJAWSKO-POMORSKIE     23  5776  78136. 147418
 3 WOJ. LUBELSKIE              24  3034 104677. 275426
 4 WOJ. LUBUSKIE               14  8572  99914. 139278
 5 WOJ. ŁÓDZKIE                24  3460  75912. 149083
 6 WOJ. MAŁOPOLSKIE            22  5758  69013. 154980
 7 WOJ. MAZOWIECKIE            42  3186  84663. 209355
 8 WOJ. OPOLSKIE               12 14888  78432. 153430
 9 WOJ. PODKARPACKIE           25  4472  71383. 130837
10 WOJ. PODLASKIE              17  3267 118747. 297644
11 WOJ. POMORSKIE              20  1728  91618. 230424
12 WOJ. ŚLĄSKIE                36  1331  34259. 152205
13 WOJ. ŚWIĘTOKRZYSKIE         14 10965  83646. 224607
14 WOJ. WARMIŃSKO-MAZURSKIE    21  7982 115112. 283802
15 WOJ. WIELKOPOLSKIE          35  3186  85219. 189988
16 WOJ. ZACHODNIOPOMORSKIE     21  9834 109070. 186911

And finally, we sort our results by the number of districts with the arrange function:

dt %›% group_by(Woj) %›% 
summarise(nr = length(Pow), min = min(Pow), avg = mean(Pow), max = max(Pow)) %›%
arrange(nr)
# A tibble: 16 x 5
   Woj                         nr   min     avg    max
   ‹chr›                    ‹int› ‹dbl›   ‹dbl›  ‹dbl›
 1 WOJ. OPOLSKIE               12 14888  78432. 153430
 2 WOJ. LUBUSKIE               14  8572  99914. 139278
 3 WOJ. ŚWIĘTOKRZYSKIE         14 10965  83646. 224607
 4 WOJ. PODLASKIE              17  3267 118747. 297644
 5 WOJ. POMORSKIE              20  1728  91618. 230424
 6 WOJ. WARMIŃSKO-MAZURSKIE    21  7982 115112. 283802
 7 WOJ. ZACHODNIOPOMORSKIE     21  9834 109070. 186911
 8 WOJ. MAŁOPOLSKIE            22  5758  69013. 154980
 9 WOJ. KUJAWSKO-POMORSKIE     23  5776  78136. 147418
10 WOJ. LUBELSKIE              24  3034 104677. 275426
11 WOJ. ŁÓDZKIE                24  3460  75912. 149083
12 WOJ. PODKARPACKIE           25  4472  71383. 130837
13 WOJ. DOLNOŚLĄSKIE           30  5629  66489  164330
14 WOJ. WIELKOPOLSKIE          35  3186  85219. 189988
15 WOJ. ŚLĄSKIE                36  1331  34259. 152205
16 WOJ. MAZOWIECKIE            42  3186  84663. 209355

The rows are sorted from the smallest to the largest number of districts in the provinces. Reverse sorting is achieved by adding at the end of our code:

arrange(desc(nr))

We have shown you how the most commonly used functions from the dplyr library work:

  • select – select columns,
  • filter – select rows based on an expression,
  • mutate – calculate new data based on existing,
  • left_join – join two tables (there are many types of join),
  • summarise -create summaries from values,
  • group_by – group by the values in a column,
  • arrange – sort rows by values in columns.

The library contains many other functions that you need to check yourself.

Leave a Reply

Your email address will not be published. Required fields are marked *