Skip to contents

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 of data.frames
  • harvester_path: list of sfs
  • g_path_alignment and g_overlap: list of ggplots

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