Understanding the structure of objects generated by the package
Source:vignettes/articles/V5-understanding-structure.Rmd
V5-understanding-structure.Rmd
The ofpetrial
package does not offer any
package-specific object classes. Rather, it uses the tibble
(tbl_df
, tbl
, data.frame
) object
from the tibble
package extensively.
Let’s first create a plot information using
prep_plot()
.
library(ofpetrial)
seed_plot_info <-
prep_plot(
input_name = "seed",
unit_system = "imperial",
machine_width = 60,
section_num = 24,
harvester_width = 30,
plot_width = 30
)
#--- check the class ---#
class(seed_plot_info)
#> [1] "tbl_df" "tbl" "data.frame"
#--- check the structure ---#
dplyr::glimpse(seed_plot_info)
#> Rows: 1
#> Columns: 11
#> $ input_name <chr> "seed"
#> $ unit_system <chr> "imperial"
#> $ machine_width <dbl> 18.288
#> $ section_num <dbl> 24
#> $ section_width <dbl> 0.762
#> $ harvester_width <dbl> 9.144
#> $ plot_width <dbl> 9.144
#> $ headland_length <dbl> 36.576
#> $ side_length <dbl> 9.144
#> $ min_plot_length <dbl> 73.152
#> $ max_plot_length <dbl> 91.44
It can be easily mutated since it is a tibble
(and also
a data.frame
). For example, you can change the plot width
like below.
#--- replace ---#
seed_plot_info$plot_width <- 60
#--- check ---#
seed_plot_info$plot_width
#> [1] 60
Let’s now create experiment plots using make_exp_plots()
for a two-input case.
#--- create plot information for another input ---#
n_plot_info <-
prep_plot(
input_name = "NH3",
unit_system = "imperial",
machine_width = 45,
section_num = 1,
harvester_width = 30,
plot_width = 45
)
#--- create experiment plots ---#
exp_data <-
make_exp_plots(
input_plot_info = list(seed_plot_info, n_plot_info),
boundary_data = system.file("extdata", "boundary-simple1.shp", package = "ofpetrial"),
abline_data = system.file("extdata", "ab-line-simple1.shp", package = "ofpetrial"),
abline_type = "free"
)
#--- glimpse ---#
dplyr::glimpse(exp_data)
#> Rows: 2
#> Columns: 14
#> $ input_name <chr> "seed", "NH3"
#> $ unit_system <chr> "imperial", "imperial"
#> $ field_sf <list> [<sf[1 x 1]>], [<sf[1 x 1]>]
#> $ headland <list> [<sf[1 x 1]>], [<sf[1 x 1]>]
#> $ exp_plots <list> [<sf[45 x 4]>], [<sf[243 x 4]>]
#> $ ab_lines <list> [<sf[1 x 2]>], [<sf[1 x 2]>]
#> $ harvest_ab_lines <list> [<sf[1 x 2]>], [<sf[1 x 2]>]
#> $ plot_width <dbl> 60.000, 13.716
#> $ harvester_width <dbl> 9.144, 9.144
#> $ machine_width <dbl> 18.288, 13.716
#> $ section_num <dbl> 24, 1
#> $ headland_length <dbl> 36.576, 36.576
#> $ side_length <dbl> 13.716, 13.716
#> $ abline_type <chr> "free", "free"
As you can see from below, there are four columns of type
list
: headland
, exp_plots
,
ab_lines
, harvest_ab_lines
. They are called
list-columns, which are just like a regular variable except it is a
list. List-columns are extremely handy when you would like to store
things like vectors or data.frame
as a cell value in a
dataset (exp_data
here).
Let’s take a look at exp_plots
variable of
exp_data
. You can access them just like you access a
regular variable using $ (or any other methods to pull a variable from a
tibble
).
exp_data$exp_plots
#> [[1]]
#> Simple feature collection with 45 features and 3 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: 353041.4 ymin: 4331461 xmax: 353354.5 ymax: 4332197
#> Projected CRS: WGS 84 / UTM zone 28N
#> First 10 features:
#> plot_id poly_line strip_id geometry
#> 1 1 1_1 1 POLYGON ((353341.4 4331463,...
#> 2 2 1_1 1 POLYGON ((353342.9 4331545,...
#> 3 3 1_1 1 POLYGON ((353344.3 4331626,...
#> 4 4 1_1 1 POLYGON ((353345.8 4331707,...
#> 5 5 1_1 1 POLYGON ((353347.2 4331789,...
#> 6 6 1_1 1 POLYGON ((353348.7 4331870,...
#> 7 7 1_1 1 POLYGON ((353350.1 4331952,...
#> 8 8 1_1 1 POLYGON ((353351.6 4332033,...
#> 9 9 1_1 1 POLYGON ((353353 4332114, 3...
#> 10 1 1_1 2 POLYGON ((353281.4 4331462,...
#>
#> [[2]]
#> Simple feature collection with 243 features and 3 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: 352993.3 ymin: 4331460 xmax: 353376.8 ymax: 4332198
#> Projected CRS: WGS 84 / UTM zone 28N
#> First 10 features:
#> plot_id poly_line strip_id geometry
#> 1 1 1_1 1 POLYGON ((353363.7 4331465,...
#> 2 2 1_1 1 POLYGON ((353365.2 4331546,...
#> 3 3 1_1 1 POLYGON ((353366.7 4331628,...
#> 4 4 1_1 1 POLYGON ((353368.1 4331709,...
#> 5 5 1_1 1 POLYGON ((353369.6 4331790,...
#> 6 6 1_1 1 POLYGON ((353371 4331872, 3...
#> 7 7 1_1 1 POLYGON ((353372.5 4331953,...
#> 8 8 1_1 1 POLYGON ((353373.9 4332035,...
#> 9 9 1_1 1 POLYGON ((353375.4 4332116,...
#> 10 1 1_1 2 POLYGON ((353350 4331464, 3...
As you can see, it is a list of two sf
objects of
experiment plots. Since, it is a list, you can access the
sf
itself like this.
#--- first element of the list ---#
exp_data$exp_plots[[1]]
#> Simple feature collection with 45 features and 3 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: 353041.4 ymin: 4331461 xmax: 353354.5 ymax: 4332197
#> Projected CRS: WGS 84 / UTM zone 28N
#> First 10 features:
#> plot_id poly_line strip_id geometry
#> 1 1 1_1 1 POLYGON ((353341.4 4331463,...
#> 2 2 1_1 1 POLYGON ((353342.9 4331545,...
#> 3 3 1_1 1 POLYGON ((353344.3 4331626,...
#> 4 4 1_1 1 POLYGON ((353345.8 4331707,...
#> 5 5 1_1 1 POLYGON ((353347.2 4331789,...
#> 6 6 1_1 1 POLYGON ((353348.7 4331870,...
#> 7 7 1_1 1 POLYGON ((353350.1 4331952,...
#> 8 8 1_1 1 POLYGON ((353351.6 4332033,...
#> 9 9 1_1 1 POLYGON ((353353 4332114, 3...
#> 10 1 1_1 2 POLYGON ((353281.4 4331462,...
Let’s now assign rates to the experiemnt plots
(exp_plots
) in exp_data
.
#--- prepare rate information ---#
seed_rate_info <-
prep_rate(
plot_info = seed_plot_info,
gc_rate = 32000,
unit = "seed",
min_rate = 16000,
max_rate = 40000,
num_rates = 5,
design_type = "ls"
)
n_rate_info <-
prep_rate(
plot_info = n_plot_info,
gc_rate = 180,
unit = "lb",
rates = c(100, 140, 180, 220, 260),
design_type = "ls",
rank_seq_ws = c(5, 4, 3, 2, 1)
)
#--- assign rates ---#
td <- assign_rates(exp_data, rate_info = list(seed_rate_info, n_rate_info))
As you can see below, td
has a very similar structure
and sets of variables (e.g., input_name
and
exp_plots
were inherited from exp_data
). This
is not surprising because we just assigned rates to the experiment plots
with assign_rates()
.
dplyr::glimpse(td)
#> Rows: 2
#> Columns: 29
#> $ input_name <chr> "seed", "NH3"
#> $ unit_system <chr> "imperial", "imperial"
#> $ field_sf <list> [<sf[1 x 1]>], [<sf[1 x 1]>]
#> $ headland <list> [<sf[1 x 5]>], [<sf[1 x 5]>]
#> $ exp_plots <list> [<sf[45 x 4]>], [<sf[243 x 4]>]
#> $ ab_lines <list> [<sf[1 x 2]>], [<sf[1 x 2]>]
#> $ harvest_ab_lines <list> [<sf[1 x 2]>], [<sf[1 x 2]>]
#> $ plot_width <dbl> 60.000, 13.716
#> $ harvester_width <dbl> 9.144, 9.144
#> $ machine_width <dbl> 18.288, 13.716
#> $ section_num <dbl> 24, 1
#> $ headland_length <dbl> 36.576, 36.576
#> $ side_length <dbl> 13.716, 13.716
#> $ abline_type <chr> "free", "free"
#> $ design_type <chr> "ls", "ls"
#> $ gc_rate <dbl> 32000, 180
#> $ unit <chr> "seed", "lb"
#> $ tgt_rate_original <list> <16000, 21333, 26667, 32000, 40000>, <100, 140, 18…
#> $ tgt_rate_equiv <list> <16000, 21333, 26667, 32000, 40000>, <82.0, 114.8,…
#> $ min_rate <dbl> 16000, NA
#> $ max_rate <dbl> 40000, NA
#> $ num_rates <dbl> 5, 5
#> $ rank_seq_ws <list> <NULL>, <5, 4, 3, 2, 1>
#> $ rank_seq_as <list> <NULL>, <NULL>
#> $ rate_jump_threshold <lgl> NA, NA
#> $ rates_data <list> [<data.table[5 x 2]>], [<data.table[5 x 2]>]
#> $ experiment_design <list> [<sf[45 x 5]>], [<sf[243 x 5]>]
#> $ input_type <list> "S", "N"
#> $ trial_design <list> [<sf[46 x 5]>], [<sf[244 x 5]>]
A trial design (experiment plots with rates assigned) has a name of
trial_design
, which is also a list-column.
#--- check the class ---#
class(td$trial_design)
#> [1] "list"
td$trial_design
#> [[1]]
#> Simple feature collection with 46 features and 4 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -16.70078 ymin: 39.11957 xmax: -16.69604 ymax: 39.12696
#> Geodetic CRS: WGS 84
#> First 10 features:
#> rate strip_id plot_id type geometry
#> 1 26667 1 1 experiment POLYGON ((-16.6965 39.12, -...
#> 2 16000 1 2 experiment POLYGON ((-16.6965 39.12073...
#> 3 32000 1 3 experiment POLYGON ((-16.6965 39.12147...
#> 4 21333 1 4 experiment POLYGON ((-16.6965 39.1222,...
#> 5 40000 1 5 experiment POLYGON ((-16.6965 39.12293...
#> 6 26667 1 6 experiment POLYGON ((-16.6965 39.12366...
#> 7 16000 1 7 experiment POLYGON ((-16.6965 39.1244,...
#> 8 32000 1 8 experiment POLYGON ((-16.6965 39.12513...
#> 9 21333 1 9 experiment POLYGON ((-16.6965 39.12586...
#> 10 21333 2 1 experiment POLYGON ((-16.69719 39.1199...
#>
#> [[2]]
#> Simple feature collection with 244 features and 4 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -16.70078 ymin: 39.11957 xmax: -16.69604 ymax: 39.12696
#> Geodetic CRS: WGS 84
#> First 10 features:
#> rate strip_id plot_id type geometry
#> 1 180 1 1 experiment POLYGON ((-16.69624 39.1200...
#> 2 140 1 2 experiment POLYGON ((-16.69624 39.1207...
#> 3 100 1 3 experiment POLYGON ((-16.69624 39.1214...
#> 4 260 1 4 experiment POLYGON ((-16.69624 39.1222...
#> 5 220 1 5 experiment POLYGON ((-16.69624 39.1229...
#> 6 180 1 6 experiment POLYGON ((-16.69624 39.1236...
#> 7 140 1 7 experiment POLYGON ((-16.69624 39.1244...
#> 8 100 1 8 experiment POLYGON ((-16.69624 39.1251...
#> 9 260 1 9 experiment POLYGON ((-16.69625 39.1258...
#> 10 100 2 1 experiment POLYGON ((-16.6964 39.12001...
Since the individual trial designs are just sf
, you can
of course wrangle them direclty if you would like to.
#--- get the trial design sf for the first input ---#
(
td_for_input_1 <- td$trial_design[[1]]
)
#> Simple feature collection with 46 features and 4 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -16.70078 ymin: 39.11957 xmax: -16.69604 ymax: 39.12696
#> Geodetic CRS: WGS 84
#> First 10 features:
#> rate strip_id plot_id type geometry
#> 1 26667 1 1 experiment POLYGON ((-16.6965 39.12, -...
#> 2 16000 1 2 experiment POLYGON ((-16.6965 39.12073...
#> 3 32000 1 3 experiment POLYGON ((-16.6965 39.12147...
#> 4 21333 1 4 experiment POLYGON ((-16.6965 39.1222,...
#> 5 40000 1 5 experiment POLYGON ((-16.6965 39.12293...
#> 6 26667 1 6 experiment POLYGON ((-16.6965 39.12366...
#> 7 16000 1 7 experiment POLYGON ((-16.6965 39.1244,...
#> 8 32000 1 8 experiment POLYGON ((-16.6965 39.12513...
#> 9 21333 1 9 experiment POLYGON ((-16.6965 39.12586...
#> 10 21333 2 1 experiment POLYGON ((-16.69719 39.1199...
#--- change the rates to all 0 ---#
(
td_for_input_1 <- dplyr::mutate(td_for_input_1, rate = 0)
)
#> Simple feature collection with 46 features and 4 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -16.70078 ymin: 39.11957 xmax: -16.69604 ymax: 39.12696
#> Geodetic CRS: WGS 84
#> First 10 features:
#> rate strip_id plot_id type geometry
#> 1 0 1 1 experiment POLYGON ((-16.6965 39.12, -...
#> 2 0 1 2 experiment POLYGON ((-16.6965 39.12073...
#> 3 0 1 3 experiment POLYGON ((-16.6965 39.12147...
#> 4 0 1 4 experiment POLYGON ((-16.6965 39.1222,...
#> 5 0 1 5 experiment POLYGON ((-16.6965 39.12293...
#> 6 0 1 6 experiment POLYGON ((-16.6965 39.12366...
#> 7 0 1 7 experiment POLYGON ((-16.6965 39.1244,...
#> 8 0 1 8 experiment POLYGON ((-16.6965 39.12513...
#> 9 0 1 9 experiment POLYGON ((-16.6965 39.12586...
#> 10 0 2 1 experiment POLYGON ((-16.69719 39.1199...
Note that this does not alter tiral_design
in
td
. So, if you want this to be reflected in
td
, you need to assign it back. The
change_rates()
function is designed to work directly on
td
to avoid this tedious procedure when modifying rates
(see this
vignette). If you really want to or must work directly on the
trial_design
part, we just showed that it is definitely
possible.
Many other functions return a tibble with list-columns. For example,
check_alignment()
checks whether the trial design would
have a mixed treatment problem.
check <- check_alignment(exp_data)
dplyr::glimpse(check)
#> Rows: 2
#> Columns: 6
#> $ input_name <chr> "seed", "NH3"
#> $ harvest_ab_line <LINESTRING [m]> LINESTRING (353285 4331407,..., LINESTRING (353285 43…
#> $ overlap_data <list> [<data.table[34 x 7]>], [<data.table[41 x 7]>]
#> $ harvester_path <list> [<sf[45 x 3]>], [<sf[45 x 3]>]
#> $ g_path_alignment <list> [NULL, <environment: 0x118af4d60>, <enviro…
#> $ g_overlap <list> [5.0000000, 6.0000000, 7.0000000, 8.0000000, 9.00000…
As you can see, its output has four list-columns and there are three different types of objects stored in them.
-
overlap_data
: list ofdata.frame
s -
harvester_path
: list ofsf
s -
g_path_alignment
andg_overlap
: list ofggplot
s
Let’s access the second of harvester_path
.
check$harvester_path[[2]]
#> Simple feature collection with 45 features and 2 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: 352970.3 ymin: 4331423 xmax: 353395.2 ymax: 4332235
#> Projected CRS: WGS 84 / UTM zone 28N
#> First 10 features:
#> ha_strip_id geometry ha_area
#> 2 1 POLYGON ((353386.6 4332235,... 5937.566
#> 3 2 POLYGON ((353372.2 4331428,... 7374.981
#> 4 3 POLYGON ((353363.1 4331428,... 7373.714
#> 5 4 POLYGON ((353353.9 4331428,... 7372.446
#> 6 5 POLYGON ((353344.8 4331428,... 7371.179
#> 7 6 POLYGON ((353335.6 4331428,... 7369.911
#> 8 7 POLYGON ((353326.5 4331428,... 7368.644
#> 9 8 POLYGON ((353317.4 4331427,... 7367.377
#> 10 9 POLYGON ((353308.2 4331427,... 7366.109
#> 11 10 POLYGON ((353299.1 4331427,... 7364.842