Draft report

aft
An Empirical Model for Ammonia Emissions
from a Broiler House
Peter Bloomfield
Department of Statistics
North Carolina State University
Raleigh, NC
April 18, 2013
Abstract
Dr
An empirical model is developed, relating ammonia emissions from a
broiler house to the flock history, and to temperature and humidity, both ambient and within the confinement. The model is fitted to data from the EPA’s
National Air Emissions Monitoring Study (NAEMS), collected at sites in
California and Kentucky. The fitted model gives in-sample predicted emissions with a prediction error of less than 4 kg per day per house. Residual
plots reveal differences between the California and Kentucky data that are
not captured by the model.
Contents
1
Introduction
3
2
The data
4
3
The model
3.1 Conversion rate . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Deposition rate . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Between flocks . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
6
7
7
1
Model inference
4.1 Ordinary least squares fitting . . . . . . . . . . . . . . . . . . . .
4.2 Weighted least squares fitting . . . . . . . . . . . . . . . . . . . .
4.3 Standard errors . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
Results
5.1 Inventory model . . . . . . . . . . . . . . . . . . .
5.2 Full model . . . . . . . . . . . . . . . . . . . . . .
5.3 Confinement model . . . . . . . . . . . . . . . . .
5.4 Weighted least squares fitting of confinement model
6
Discussion
8
8
8
9
aft
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
10
10
15
20
26
30
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Dr
A R scripts for creating data frames
A.1 Combined data . . . . . . . . .
A.2 California data . . . . . . . . .
A.2.1 Animal data . . . . . . .
A.2.2 Emissions data . . . . .
A.2.3 House environment data
A.2.4 Weather data . . . . . .
A.3 Kentucky data . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
32
32
32
33
35
36
37
38
B R scripts for model fitting
B.1 The emission function . . . . . . .
B.2 The inventory model . . . . . . .
B.3 The full model . . . . . . . . . . .
B.4 The confinement model . . . . . .
B.5 WLS fit of the confinement model
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
39
39
41
41
42
43
C R scripts for figures and summaries
C.1 Observations . . . . . . . . . .
C.2 Deposition functions . . . . . .
C.3 Residual plots . . . . . . . . . .
C.4 Correlation plots . . . . . . . .
C.5 Summaries . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
45
45
46
46
47
48
2
.
.
.
.
.
List of Figures
15
Total bird mass and emissions over time, by house . . . . . . . . .
The fitted deposition function for the inventory model . . . . . . .
Observed and fitted emissions for the inventory model . . . . . . .
Residual and fitted emissions for the inventory model . . . . . . .
Conversion rate for the full model . . . . . . . . . . . . . . . . .
Observed and fitted emissions for the full model . . . . . . . . . .
Residual and fitted emissions for the full model . . . . . . . . . .
Conversion rate for the confinement model . . . . . . . . . . . . .
Observed and fitted emissions for the confinement model . . . . .
Residual and fitted emissions for the confinement model . . . . .
Autocorrelation functions of residuals for the confinement model .
Cross correlation of residuals for the two California houses . . . .
Observed and WLS fitted emissions for the confinement model . .
WLS weighted residuals and fitted emissions for the confinement
model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
WLS estimated conversion rate for the confinement model . . . .
Dr
List of Tables
1
2
3
4
1
5
12
13
14
17
18
19
21
22
23
24
25
27
aft
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Fitting results for the inventory model . . . . . . . . . . . . . .
Fitting results for the full model . . . . . . . . . . . . . . . . .
Fitting results for the confinement model . . . . . . . . . . . . .
Weighted least squares fitting results for the confinement model
28
29
. 11
. 15
. 20
. 26
Introduction
As part of EPA’s National Air Emissions Monitoring Study (NAEMS), daily ammonia emissions were measured at two broiler houses at a California Animal
Feeding Operation (AFO), and from one broiler house at each of two Kentucky
AFOs. Also recorded were operational details such as:
• the numbers of birds present and their average weight;
• dates of the intermittent removal of all or part of the litter;
• temperature and humidity both inside and outside the house.
3
2
The data
aft
The objective of the study was to provide observational data to support the
development of an Emissions-Estimating Methodology (EEM); that is, a tool for
predicting ammonia emissions from the operational and environmental data.
A summary report and a data spreadsheet for the California site may be found
at http://www.epa.gov/airquality/agmonitoring/ca1b.html.
A summary report and a data spreadsheet for the Kentucky sites may be found at
http://www.epa.gov/airquality/agmonitoring/ky1b.html1 .
Dr
Several flocks were grown in each house during the period of observation. Figure 1 shows the history of emission for each house and of the total mass of birds.
Note that some emission data was recorded between flocks; these are shown in the
broken line in the figure. Between flocks, the litter was either partially replaced in
a “decake” operation or completely replaced in a “loadout” or “cleanout” operation; loadout dates are shown in the figure.
Evidently the emissions are generally higher when the birds are older and
heavier (Pescatore et al., 2005). Closer examination shows that emissions are
lowest after a loadout; in the first few days of a young flock introduced after only
decaking, the emissions are not as low, and in most cases initially decline. This
suggests that ammonia emissions arise from nitrogen-rich manure that accumulates in the litter (Elwinger and Svensson, 1996).
3
The model
The concept of the empirical model developed below is that the birds excrete
nitrogen-rich manure into the litter at a rate that depends on their average body
mass, and that the nitrogen is then converted to ammonia at a rate proportional to
the amount of nitrogen in the litter. The time step is one day; in this discrete time
model, deposition is arbitrarily viewed as occurring first, followed by emission.
To be specific, if lt is the amount of nitrogen in the litter on day t (measured in
kg of potentially emitted ammonia), then
lt = lt−1 − et−1 + dt ,
1
(1)
The Kentucky data were initially made available without the environmental component; the
complete data set is in the file labeled “Data (relative humidity and temperature)”.
4
NH3 (kg/day)
30
0
aft
10
20
60
40
20
0
Mass (1000 kg)
ca1bHouse10
2008
2009
NH3 (kg/day)
30
0
10
20
60
40
20
0
Mass (1000 kg)
ca1bHouse12
2008
2009
NH3 (kg/day)
30
20
10
Dr
0
0
60
40
20
Mass (1000 kg)
ky1b15
2007
2007
Figure 1: Total bird mass (red, left axis) and emissions (blue, right axis) over
time, by house; emissions are shown by a broken line when no birds were present;
bird mass is shown by a broken line when no emissions were measured; vertical
lines (green) mark “loadout” dates.
5
NH3 (kg/day)
30
0
10
20
60
40
20
0
Mass (1000 kg)
ky1b33
where et−1 is the amount emitted the previous day, and dt is the amount deposited
in manure. Also
et = λt lt ,
(2)
aft
where λt is the rate of conversion, possibly dependent on ambient conditions such
as temperature and relative humidity. Finally,
dt = nt f (mt ),
(3)
where nt is the number of birds in the flock, mt is the average body mass in the
flock, and f (·) is a function, to be determined, representing the per-bird per-day
deposition rate.
3.1
Conversion rate
The conversion rate λt is assumed to follow a linear model on the logarithmic
scale:
log λt = xTt β,
(4)
Dr
where xt is a vector of covariates, consisting of a constant element 1 for the intercept, and some or all of temperature and relative humidity, both ambient and as
measured within the confinement; β is a matching vector of parameters. Various
models are constructed by choosing which environmental variables are included
in xt .
This model always produces positive rates, but could conceivably produce
λt > 1, which by equation (2) would mean that more ammonia was emitted than
could be generated from nitrogen in the litter; the issue could be avoided by using
the logistic form
λt
= xTt β,
logit(λt ) = log
1 − λt
because the solution
exp(xTt β)
λt =
1 + exp(xTt β)
always satisfies 0 < λt < 1. However, the results will show that the issue does
not arise in practice, because the estimated λt 1, so the logarithmic model (4)
was used. The logarithmic model has the convenient feature that the effect of
each covariate on λt is multiplicative, which simplifies the interpretation of the
corresponding parameter β.
6
3.2
Deposition rate
(5)
aft
The per-bird per-day deposition rate is assumed to be of the form
m m k
f (m) = γ
exp 1 −
,
θ
θ
where m is the average bird mass, and γ, θ, and k are the parameters of the model.
The parameters have the following interpretations:
γ > 0: the maximum deposition rate;
θ > 0: the per-bird mass at which the deposition rate is maximized;
k > 0: a shape parameter; for small m,
f (m) ∼ m × γ
k
e k
θ
;
if k = 1, then for small m deposition is approximately proportional to m.
This function is an unnormalized and reparametrized version of the gamma probability density function.
Between flocks
Dr
3.3
Equation (1) is assumed to hold when birds are present. Between flocks, litter is
either partly or fully replaced, ventilation is managed differently, and other possible operational deviations mean that the model may not hold. Emissions on
those days are therefore not used in the model fitting described below. However,
the nitrogen content of the litter when the new flock is introduced is an important determinant of the initial emissions, as may be seen from close inspection of
Figure 1.
To maintain continuity, Equation (1) is therefore used for all days, with the
modification that if t is the date of a loadout operation, lt is set to zero, while if
t is the date of a decake operation, lt is multiplied by a factor ψ, estimated as an
additional parameter.
Basically, this amounts to the simplifying assumption that when the new flock
is introduced, the litter condition is the same as if the only variation in operation
were the loadout or decake event.
At the Kentucky sites, the condition of the litter when the first flocks were introduced is ambiguous. The summary report (Southeastern Broiler Gaseous and
7
4
4.1
Model inference
aft
Particulate Matter Emissions Monitoring Project, 2009) states that “Both houses
had new bedding at the beginning of monitoring”, but Table 1 in that report indicates that the litter condition for Flock 1 at both sites was “BUL”, meaning
“Built-up litter”, and not “NB”, meaning “New bedding”. Figure 1 suggests that
the litter contained accumulated nitrogen. In the model fitting described below,
the initial
nitrogencontents in those houses were treated as additional parameters
f = fky1b15 , fky1b33 .
Ordinary least squares fitting
Each version of the model is fitted using nonlinear ordinary least squares (OLS):
minimize
X
S OLS (β, γ, θ, k, f) =
(yt − et )2 ,
t
Dr
where yt is the observed ammonia emission on day t and et is calculated from
equations (1–5). Fitting was carried out using the R (R Core Team, 2012) function
nls().
Days on which no emissions data were recorded are necessarily omitted from
the sum. As discussed in Section 3.3, the emission equation (2) may not hold
between flocks, so those days are also omitted.
To maintain continuity in the calculation of lt , missing data in each covariate
are replaced by the mean of the non-missing values. However, because λt is directly involved in the calculation of et , a day on which any covariate is missing is
also omitted from the sum.
4.2
Weighted least squares fitting
Residuals from the fitted models will be seen to suggest that emissions tend to
be more variable when they are high than when they are low. In such situations,
models are sometimes fitted using weighted least squares (WLS): minimize
X
S WLS (β, γ, θ, k, f) =
wt (yt − et )2 ,
t
where the weights wt give greater weight to the more precise observations. The
specification of weights is an option in the nls() method.
8
aft
When a model is correctly specified, and the observations are uncorrelated
with variances inversely proportional to the weights, WLS estimates are optimal.
In that case, using weights is just a matter of the efficient use of the observed data.
In practice, a model is usually regarded as an approximation to a true underlying
relationship, and in this case the effect of introducing weights is to emphasize
a good fit where the weights are high, at the expense of a poorer fit where the
weights are low. In the present case, that would mean a better fit for low emissions
and a poorer fit for high emissions, within the data used for fitting. It could,
however, result in better predictions for both low and high emissions, in new data.
Rarely are good weights known in advance. More commonly, they are estimated as the inverses of estimated variances. A common model is
(6)
var(yt ) = σE(yt )κ 2 ,
which for κ > 0 gives higher variance, and hence lower weight, as E(yt ) increases.
The exponent κ may be estimated from the model residuals; the original model is
then refitted; estimation of the model and then the weights is iterated to convergence.
One model was fitted by this iterated WLS method, and the results reported
below.
Standard errors
Dr
4.3
The nonlinear least squares fitting function nls() calculates and reports standard
errors for the parameter estimates. However, these are valid only when the observations are uncorrelated with constant variance (or, if nonconstant weights are
used, with variance inversely proportional to the weights). As will be seen below,
in these data the variance does not appear to be constant, so nls() standard errors for OLS estimates are not credible. In the WLS fit, the heteroscedasticity is
at least partially corrected, but serial correlation remains, and renders the nls()
standard errors unreliable.
The sandwich package (Zeileis, 2004, 2006) implements the calculation of
standard errors that are valid when the observations are serially correlated and
heteroscedastic. In the present case, when the data are stacked into a single vector


 Yca1bHouse10 
 Y

ca1bHouse12 


 ,
Y = 

 Yky1b15

Yky1b33
9
aft
its covariance matrix may be assumed to be block-structured:


0 
 Σ1,1 Σ1,2 0
 Σ
Σ
0
0 
var(Y) =  2,1 2,2
.
0 Σ3,3 0 
 0

0
0
0 Σ4,4
The rationale for the zero blocks is as follows:
• The California and Kentucky data are collected over disjoint periods of time
and have no apparent common factors to cause correlation;
• The data for the two Kentucky houses are essentially contemporaneous, but
the sites are 40 miles apart, and cross-correlations calculated from residuals
show no substantial correlation.
Dr
The two California houses are colocated, however, and residuals are highly crosscorrelated, so the Σ1,2 block cannot be assumed to be zero.
The diagonal blocks contain heteroscedasticity and serial correlation, and estimates for each of them can be constructed using functions from the sandwich
package. The off-diagonal block Σ1,2 is more problematic. The R code listed in
Appendix C.5 implements a method of calculation that can be shown to be correct
for heteroscedastic but uncorrelated data; its use for correlated data, as here, has
not been validated. It should at least offer an improvement over the nls() standard errors. Standard errors reported below were calculated using this method.
5
5.1
Results
Inventory model
The simplest model uses only the bird inventory data. No environmental data are
used, and xt = 1. Thus the conversion rate λt is the constant exp(β0 ). Parameter
estimates and standard errors are given in Table 1. The residual standard deviation
is 3.943 kg per day.
These estimates have the following interpretations:
β0 = −2.5689: the constant conversion rate λ = exp(−2.5689) = 0.0766; that is,
7.66% of the nitrogen in the litter is emitted as ammonia, per day; equivalently, the mean residence time of nitrogen in the litter is 1/0.0766 ≈
13 days.
10
Table 1: Fitting results for the inventory model
Std. Error
-2.5689
1.2156
1.5606
1.7023
0.7000
34.4083
88.7000
0.2575
0.1283
0.1782
0.2733
0.2203
14.9509
21.4986
aft
β0
γ
θ
k
ψ
fky1b15
fky1b33
Estimate
γ = 1.2156: the maximum rate of deposition of nitrogen in the manure is 1.2156
grams (of potential ammonia) per bird per day.
θ = 1.5606: the maximum deposition rate is achieved when the birds weigh an
average of 1.5606 kg.
Dr
k = 1.7023: the shape of the deposition function is governed by k; Figure 2 shows
the estimated deposition function, incorporating the effect of this value of
k, as well as the estimated values of γ and θ; note that although k > 1, the
deposition rate initially increases roughly proportionally to bird mass.
ψ = 0.7: the impact of decaking is estimated to reduce the nitrogen content of
the litter to 70% of its previous level; equivalently, 30% of the nitrogen is
removed by decaking.
fky1b15 = 34.4083, fky1b33 = 88.7000: the intial nitrogen content of the litter in
Tyson #1 House 5 is estimated to be 34.4 kg, and in Tyson #3 House 3
to be 88.7 kg.
Figure 3 shows the fitted values and the observed emissions. The model fits
better at low emissions than at high levels of emission; it also systematically
under-estimates the higher levels in the California houses. The fit is erratic for
higher levels in the Kentucky houses.
Figure 4 plots the residuals against the fitted values. The residuals are relatively small at low fitted values, and increase in magnitude at higher fitted values. For each house, the residuals were smoothed using lowess() (with span f
11
1.2
0.5
aft
0.8
0.4
0.0
Nitrogen excretion, g/(bd)
0.0
1.0
1.5
2.0
2.5
3.0
Average bird mass, kg/b
Figure 2: The fitted deposition function for the inventory model
These curves indicate that California emissions are systematically overestimated when the fitted value is around 10 kg per day and under-estimated when
the fitted value is around 20 kg per day. Conversely, the Kentucky emissions are
under-estimated when the fitted value is around 10 kg per day and over-estimated
when the fitted value is more than 20 kg per day.
Dr
= 0.5).
12
30
2008
aft
20
10
0
NH3 (kg/day)
ca1bHouse10
2009
30
20
10
0
NH3 (kg/day)
ca1bHouse12
2008
2009
30
0
10
Dr
20
NH3 (kg/day)
ky1b15
2007
30
20
10
0
NH3 (kg/day)
ky1b33
2007
Figure 3: Observed (blue) and fitted (black) emissions for the inventory model;
broken lines indicate days that were omitted in fitting the model.
13
aft
10
5
0
−5
●
●
ca1bHouse10
ca1bHouse12
ky1b15
ky1b33
●
●
Dr
−15
●
●
●
●
●
●
●
● ●
● ●●
●
●
● ● ●
●
●
●
●
●●
●
●
● ●●
●●●
●
●● ●
●
●●● ●●
● ●
● ● ●
●
●
●
●
●
● ●● ●
●●
●
●
●
●● ●●
●
●
●●●
● ● ●●
● ●● ●
●
●
●
●
●
●
●
● ●●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●●
●
● ●● ●●
●●
●
●
● ● ●
●●● ● ● ● ●
●●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●● ●●
●
●
●● ● ● ●● ● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ● ●● ●●● ●●
●
●●
●
●● ● ●
●
●●
●●●
●●
●●●
●
●
●
● ● ●
●
● ● ●
●
●●
●
●●
● ●● ●
●
● ●●●●
●●
●
● ●
●●●●●●
●
●
● ● ●● ●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●● ●
●
●●●
● ●
●●
●●
●●
●●
●
●
●●
●
●●●●●
●●●●
●
●
● ●● ● ●
●●
●
●
●
●● ●●
●
●●
●
●●● ● ●●●
●
●
●
●
●
●
●
●
●
●●
●●
● ●●
●
●●●
●
●
●●
●
●
● ●
●●● ●
●
● ●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●●● ●● ●●
● ● ●
●
●
●
●●
●
●●
● ●●●
●
●
●
●● ●
●
●
●
●●
●
●
●● ●●
●●
●
●
●●●
●
●
●●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●●
●●
●●
●
●
● ●●
● ●●
●
● ●● ● ●●●●● ● ● ● ●● ● ● ●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●●●
●
●
●
●
●●
●
●●● ●
●
●
●
●
●
●●
●
●●
●
●
●
●
●
●
●●●●●
●
●
●● ●
●●
●●
●●
●●
● ●●●●
●
●
●●
●
●
●
●
●●● ●
●
●
●
●
●
●
● ●●●●●● ●●● ● ●
●
●
●●
●
●
●● ●●
●
●●●●
●
●●
●
●
●●
●
●
●●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ● ● ●●
●
●● ●
●
●●
● ● ●●
●
●
● ●● ● ●● ●● ● ●●
●
●●
●●
●
●●
●
●
●
● ●
● ●● ●
●
●
●
●
●●
●
●
●
●
●
●
●
●
● ●●●
●
●
●
●
●
●
●
●
●●
●
●
●
●● ●
●
●
●
●
●
●
●
●
● ●● ●● ●
●
●
●●
●●
●●
● ●●●●
●●
●●
●●●●
●●
●
●
●●
●●●
●●
● ●●
●
●●●
●
●●●●●●
●
●● ● ●
●
●●
● ● ● ● ● ● ●● ●●
●
●●
●
●
●
●
●
●● ●
●●
●
●● ●
●
●
●●
●
● ●●
●
●
●
●
●
●●
●
●
●
●
●
●●●●●● ●
●
●●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●●
● ● ● ●
●
●●
●●●●
●
●
●
●
● ●
● ● ●
● ●●●●●●
● ●
●
●
●
●
●
●●
●
● ●●
●●
●
●
● ●
●
● ●
● ●●●●
●
● ●●
●
●
●●
●
●
●
●
●●
●
0
5
10
15
20
25
Figure 4: Residual and fitted emissions for the inventory model; data points are
colored by house; lowess() curves are shown for each house.
14
Table 2: Fitting results for the full model
5.2
Std. Error
-2.8274
0.008669
0.001912
0.027872
0.007695
1.3891
1.4961
1.8533
0.4583
45.4718
109.7547
0.2080
0.003302
0.001308
0.008219
0.002215
0.1299
0.1168
0.2197
0.0961
19.2625
41.2758
Full model
Standardized
Estimate Std. Error
aft
β0
βATemp
βARH
βCTemp
βCRH
γ
θ
k
ψ
fky1b15
fky1b33
Estimate
0.06812
0.02712
0.12940
0.08388
0.02569
0.01726
0.03919
0.02261
Dr
Temperature and relative humidity may be expected to influence the conversion of
litter nitrogen into ammonia. The variables that were available for all houses are:
ATemp: ambient temperature;
ARH: ambient relative humidity;
CTemp: temperature within the confinement;2
CRH: relative humidity within the confinement.
Parameter estimates and standard errors for an extended model in which xt includes all these variables are given in Table 2. The residual standard deviation is
3.674 kg per day. Parameters that are shared with the inventory model all changed
relatively little; all 95% confidence intervals overlap.
Each regression variable was centered by subtracting its mean. The interpretation of β0 is therefore that exp(β0 ) = 0.0592 is the conversion rate on a
2
The Kentucky data contain measurements of temperature at three different locations within
each confinement; in these models, the temperature at location SW 1, “in the brooding end of the
house”, was used.
15
Dr
aft
hypothetical day when all variables are equal to their means. The other regression coefficients are interpreted in a way analogous to linear regression. Thus
for instance βATemp = 0.008669 is the change in log(λt ) associated with a 1◦ C increase in ambient temperature, with the other variables held constant. Since this
change is small, it is also, to a good approximation, the fractional change in λt , and
100 × βATemp = 0.8669 is the percentage change. That is, a 1◦ C increase in ambient temperature is associated with close to a 1% increase in the rate of conversion
of litter nitrogen to ammonia, and a 1◦ C increase in confinement temperature is
associated with close to a 3% increase in the rate of conversion.
The regression coefficients are tabulated in “standardized” form as well as
unstandardized. A standardized coefficient is the coefficient estimated when the
corresponding variable is standardized by dividing by its standard deviation. The
standardized coefficients are dimensionless, and may be interpreted as measuring
the contribution of the variable to the model. Viewed in this way, they suggest
that the confinement variables are more important than the ambient variables, and
that temperature is more important than relative humidity. T -statistics computed
by dividing each parameter estimate by its standard error lead to the same evaluation, and additionally that the coefficient of ambient relative humidity is not
significantly different from zero.
Figure 5 shows the fitted conversion rate λt . The figure indicates substantial
variation in the apparent conversion rate, from a low of less than 4% per day to a
high of over 8% per day.
Figure 6 shows the fitted values and the observed emissions for this model,
and Figure 7 plots the residuals against the fitted values. The figures are generally similar to those for the inventory model, but show modest improvements. In
Figure 6, the fitted values show some local features that are also visible in the observed emissions, indicating that some of the day to day variability in emissions
is related to these variables. In Figure 7, the most extreme residuals are smaller
than in Figure 4, but the systematic over- and under-estimation patterns remain.
16
2008
aft
0.04
0.00
λt
0.08
ca1bHouse10
2009
0.04
0.00
λt
0.08
ca1bHouse12
2008
2009
0.00
Dr
0.04
λt
0.08
ky1b15
2007
0.04
0.00
λt
0.08
ky1b33
2007
Figure 5: Conversion rate for the full model; broken lines indicate days that were
omitted in fitting the model.
17
30
2008
aft
20
10
0
NH3 (kg/day)
ca1bHouse10
2009
30
20
10
0
NH3 (kg/day)
ca1bHouse12
2008
2009
30
0
10
Dr
20
NH3 (kg/day)
ky1b15
2007
30
20
10
0
NH3 (kg/day)
ky1b33
2007
Figure 6: Observed (blue) and fitted (black) emissions for the full model; broken
lines indicate days that were omitted in fitting the model.
18
aft
10
5
0
−5
ca1bHouse10
ca1bHouse12
ky1b15
ky1b33
Dr
−10
●
●
●●
●
● ● ●●
●●
●
●●
●
●
●● ● ●●
●
● ●
● ●● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
● ●
●●
●●● ●
●● ●
●●●●●●
●
●
●
●●
●
● ● ●
●●●
●
●
●●
● ● ●●
● ●
●
●●●●● ●
● ● ●●
●
●●
●
●●●
●
●●
●
●●●
●●
●
●● ●● ● ● ●
●
●●●
● ● ●
● ●●● ● ●●
●●●
●●
●●
●
●
● ●
●●
●
●●
●
●●●
●●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●●
●
●●
●●
●
●
●● ●●●
●●●
●
●
● ● ●●● ● ●
●
●●
●
●
●● ●
●
●
●
●
● ● ● ●●●●● ●●●●●● ●
●
●●
●
● ●●●
●
●
●
●
●
●
●
●●
● ●● ●
●
●
●●
● ●
●
●
●●
●
●
●●
●●
●●
●●●
●
●●●
●
●●
●
●●● ●
●
●
●●●
●●
●●●
●● ●
●
●
●● ●
●●
●● ●
●●
●
●
●●●●
●●
●●
●
●
●●
●●
●
●●
●●
● ●●●
●
●● ●●
●●
●
●●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●● ●
● ●●
●●
● ●●●
●●●
●●
●
● ●
● ●
● ● ●● ● ●
●●●●
●● ● ●
●
●●
●●
●●
●
●●
●●
●
●
●●
●●●
● ●
●●
●
● ●
●●●
●● ●●●
●
● ●
●●
●
●
●●●
●
●
●● ●
●
●
●
●
●● ●
●
●
●●●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●●●
●
●
●
●
●
●
●
●
●● ●● ●●● ●●●
●● ●●●
●
●●●
●
●
●
●
●
●
●● ●●●
●
●
●
●
●
●
●
●
●●● ●●
●
●
●●
●
●
●
●
●
●
●
●
● ●
●● ● ●
●
●● ●●●
●
●
●
●●●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●●●●
● ●●●●●
●
●
●
●
●
●
●● ●●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●● ●
●
●
●
●●
●
●
●
●
●
●●●
●
●●
●
●●●
●●
●
●
●
●
●
●
●
●●●
●
●
●
●
●
●●● ●
●●
●
●
●
●
●
●●
●● ●
●
●
●
●
● ● ●●
●
●
● ●●● ●●
●
●● ●
●●● ●
●
●
●●
●
●
●
●● ●●●●
●
● ●●
●
●
●
●
●● ● ●
●
●
●
●
●●
●
●
●
● ● ●●
●
●
●
● ●
●● ●
●●●
●
●●●
●
●● ●
●
●
●● ● ● ●●● ●●
●
●
●● ●
●
●
●●
● ●●
●
● ●
●●
●
●●
●●
● ●
●
●
●
●
●
● ●●
●
●
●
●
●
●
●
●
●
●
●
● ● ●●● ●
● ●
● ●●●
●
●●●
●
●
●
●●
● ●●● ● ●
● ●● ●●
●● ●
●
● ●●
●
●●
●● ● ● ●
●
●●
● ● ●● ● ● ●● ●
●
●
●
●
●
●
● ● ●● ●
●
● ●
●●
●●● ● ●
●●
●
●
● ●
● ●
●●● ● ● ● ●
●
● ●
●
●
● ●
●
● ●●
●
●
●
● ●●
●
●
●● ● ● ●
●
●
●
●
● ●
●
●
●
●
0
5
10
15
20
25
30
Figure 7: Residual and fitted emissions for the full model; data points are colored
by house; lowess() curves are shown for each house.
19
Table 3: Fitting results for the confinement model
5.3
Std. Error
-2.6910
0.0412
0.0103
1.3516
1.5782
1.8462
0.4768
35.8407
85.9788
0.2253
0.0077
0.0020
0.1279
0.1383
0.2384
0.1204
13.6760
30.0526
Confinement model
Standardized
Estimate Std. Error
aft
β0
βCTemp
βCRH
γ
θ
k
ψ
fky1b15
fky1b33
Estimate
0.1913
0.1118
0.0379
0.0225
Dr
Parameter estimates and standard errors for a reduced model in which xt includes
only the confinement variables are given in Table 3. The residual standard deviation is 3.710 kg per day.
The parameters shared with the inventory model again have estimated values
similar to those in the two previous models. The coefficients of the confinement
temperature and relative humidity are both higher than in the full model. The
standardized coefficient of temperature is close to the sum of the standardized
temperature coefficients in the full model, suggesting that little information has
been lost; the standardized coefficients of relative humidity have a similar relationship.
Figure 8 shows the fitted conversion rate λt for the confinement model. The
variations in the California rates are more pronounced than for the full model
(Figure 5). Otherwise the results are similar to those for the full model.
Figure 9 shows the fitted values and the observed emissions for the confinement model. The fitted values show the same local features as for the full model
(Figure 6). Leaving out the ambient variables has led to no visible deterioration
of the fitted values.
Figure 10 plots the residuals against the fitted values. The graph is very similar
to that for the full model (Figure 7).
Figure 11 shows the autocorrelation functions of the residuals, by house. The
one-day autocorrelation is around 0.85 - 0.86 for each house. This high correlation
20
2008
aft
0.04
0.00
λt
0.08
ca1bHouse10
2009
0.04
0.00
λt
0.08
ca1bHouse12
2008
2009
0.00
Dr
0.04
λt
0.08
ky1b15
2007
0.04
0.00
λt
0.08
ky1b33
2007
Figure 8: Conversion rate for the confinement model; broken lines indicate days
that were omitted in fitting the model.
21
30
2008
aft
20
10
0
NH3 (kg/day)
ca1bHouse10
2009
30
20
10
0
NH3 (kg/day)
ca1bHouse12
2008
2009
30
0
10
Dr
20
NH3 (kg/day)
ky1b15
2007
30
20
10
0
NH3 (kg/day)
ky1b33
2007
Figure 9: Observed (blue) and fitted (black) emissions for the confinement model;
broken lines indicate days that were omitted in fitting the model.
22
ca1bHouse10
ca1bHouse12
ky1b15
ky1b33
0
5
10
●
●
●
aft
10
5
0
−5
−10
●
● ●
●●
● ●●
●
●
● ●●
●
●
● ●
●
● ●●
●●
●●
●
●●
●
● ●
●
●
●
●
●
●
●●
●
●●
●●
● ●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●●
●●
●
● ●●
●●
●● ●● ●● ● ● ● ● ● ● ●●
●●●●●
●● ●● ●
●
●
●
●
●●
●
●●
●●
●●●●
●●●
●●●●●
●
●
●●
●●●
●●
●●● ●●●
●
●
●
●
●
●●
●
●●
●
●
●●
●● ●
●●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●● ● ●●●
● ●●
●
●●
●●
●
●
● ● ●●
●●
●
●
●●
●● ●
●●
●
● ●●
●
● ●●
●●●
●
●
●●
●●
●●
●●
●
●
●
●
●
●●● ●
●
●●
●
● ●
●
●
●
●
●●●●
●●●●●
●
●
● ●●
●●●
●●
●
●●
● ●●●● ●
●● ●
●
●
●●
●●
●●●
●●●
●
●
●
●
●
●
●
●
●●●
●
●
●
●●
●
●
●●
●
●
●
● ●
●●
●
●
●
●
●
●● ● ●
● ●●
●
●●
●
●●
●
●
● ●
●●
●
●
●● ●●●●
●● ●
●
●●
●
●
●
●
● ●● ●●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●●
●● ●● ●
●
●
●●
●
●
●
●● ●
●●
● ●●
●
●
●●● ●
●
●
●●
●
●
●●
●
●●
●●●●
●
●●●●
●● ● ● ●●● ●
●
●
●
●
●●
●
●●
● ●
●●
●
●
●
● ●
●
●
●
●
●●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
● ●● ●
●
●●
●●
●● ●●
●
●●
●
●
●
●
●
●●
●●●
●
●
●
●
●
●
●● ●
●
●
●
●
● ●●●
●●
●
●●
●
●
●
●
●●●●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
● ●●●● ● ●● ●● ●
●
●
●
●
●
●
●
●
●
●
● ●●
●●
●
●
●
●●●
●
●
●
●●
●
●
●
●
● ●●●●●●●● ● ●
●
● ●●● ●●●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●●●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
● ●●●
●
●
●
●
●
●●●
●
●
●●●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●● ● ●
●●●●
●
●
● ●●● ●
● ● ●●
●● ●
●●●
● ● ●● ●
●
●● ●
●●
●
●●
●●●
●●
● ●●
●
●
●
●●
●
●●●
●●
●●
●●●
●●●
●
●●
●
●●
●● ● ●
●
●
●
●●
● ●
●● ●
●
● ●●
●●● ●
●●
●●●●●
●●
●
●
●● ● ●● ● ●
●●● ●
●
●
●
●
●
●
● ●●
●●
●
●●●●
●
●
●
●
●
●
●
●●
●
●
●
●
● ●
●
●●
● ● ●●● ●
●● ●
●●●
● ●●
● ●
●
●●
● ● ●●
● ●
●
●
●
●
●
●●
●
●
●
●
●
●● ●● ●
● ●
●
● ●
●
●
●● ●
●
● ●
●●
●
●●
●
●
●
●●
● ●●
●
●●
●
●●●●
●
●
●
●● ● ●●● ●
●
●
● ●●
●
●
●
●
15
20
25
30
Figure 10: Residual and fitted emissions for the confinement model; data points
are colored by house; lowess() curves are shown for each house.
Dr
and the slow decay indicate that effects other than those used in the model caused
persistent over- and under-prediction of emissions. Autocorrelations for the other
models are not shown, but are quite similar.
Figure 12 shows the cross-correlations of residuals for the two California
houses. The same-day correlation (lag 0) is close to 0.9, and the cross correlation decays at much the same rate as the autocorrelations in Figure 11.
Autocorrelation and cross correlation graphs for the other models are not
shown, but are similar to those shown here.
23
−0.2
−0.2
0.2
0.2
ACF
ACF
0.6
0.6
aft
1.0
ky1b15
1.0
ca1bHouse10
0
5
10
15
20
Lag
25
0
5
10
15
20
25
20
25
Lag
ky1b33
0.4
ACF
−0.2
0.0
0.2
ACF
0.6
Dr
0.8
1.0
ca1bHouse12
0
5
10
15
20
25
0
Lag
5
10
15
Lag
Figure 11: Autocorrelation functions of residuals for the confinement model, by
house; plotted at lag τ is the correlation between the residual on a given day, and
the residual τ days earlier.
24
aft
0.2
Dr
−0.2
ACF
0.6
ca1bHouse10 & ca1bHouse12
−20
−10
0
10
20
Figure 12: Cross correlation of residuals for the two California houses; plotted
at lag τ is the correlation between the residual for House 10, and the residual for
House 12 τ days earlier.
25
Table 4: Weighted least squares fitting results for the confinement model
5.4
Std. Error
-3.6366
0.0394
0.0116
2.2224
1.4090
1.9448
0.2431
85.7265
177.9599
0.2864
0.0077
0.0018
0.4336
0.1127
0.3135
0.0442
48.4126
68.8095
aft
β0
βCTemp
βCRH
γ
θ
k
ψ
fky1b15
fky1b33
Estimate
Weighted least squares fitting of confinement model
Dr
Parameter estimates and standard errors for the confinement model of Section 5.3
re-estimated using weighted least squares are given in Table 4. The exponent κ in
Equation 6 was estimated to be 0.570. The residual standard deviation is 3.826 kg
per day.
Figure 13 shows the WLS fitted values and the observed emissions for the
confinement model. The fitted values show the same local features as when the
model is fitted using ordinary least squares (Figure 9).
Figure 14 plots the residuals against the fitted values. The graph is quite different from that for the OLS fitted model (Figure 10); these are weighted residuals,
which are the conventional residuals multiplied by the square roots of the corresponding weights. If the modeled variance function were correctly specified,
these would show no change in scale from low to high fitted values. The wedge
shape in Figure 10 is indeed no longer present. However, the lowess() curves
indicate that the difference between the California and Kentucky sites persists.
Figure 15 shows the WLS fitted conversion rate λt for the confinement model.
Aside from scale, the graph shows much the same variation in conversion rate
as in the OLS version, Figure 8. The WLS estimated conversion rates are in
absolute value, however, less than half the OLS estimated rates. Close comparison
of Tables 3 and 4 explains the difference. While the covariate coefficients βCTemp
and βCRH are similar in the two fits, the intercept β0 is lower by around 1, and as
a result the estimated conversion rates are lower by a factor of around e−1 = 0.37.
This is offset by an increase in the deposition rate model, where the estimated
26
30
2008
aft
20
10
0
NH3 (kg/day)
ca1bHouse10
2009
30
20
10
0
NH3 (kg/day)
ca1bHouse12
2008
2009
30
0
10
Dr
20
NH3 (kg/day)
ky1b15
2007
30
20
10
0
NH3 (kg/day)
ky1b33
2007
Figure 13: Observed (blue) and WLS fitted (black) emissions for the confinement
model; broken lines indicate days that were omitted in fitting the model.
27
ca1bHouse10
ca1bHouse12
ky1b15
ky1b33
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
● ● ●●●
●●●● ● ● ●
●
●
●
●
●
●
● ●
●
●
●●●● ●●
●
●
●
●
●
●
● ●
●●●
●●●●
● ●●●● ●●
●● ● ●●
●
●●
●
● ●● ●● ●
● ●
●●
●
●● ● ● ● ●● ●
●●
●●● ● ● ● ●
●●
●
●
●
●●●●
●●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●● ●
●●
●
●●
● ●● ● ●
●●
●●
●●
●●
●
●
●●● ● ●●
●●● ●
●
● ●
●●
●
●
●
●●
●
●
●
●
●
●●● ●
●
●●
●●
●
●●
●
● ●
● ● ●●
●
●●●●
●
●●
● ●
●
●
●●●● ●
● ●●●
●●
●●● ●●●●
●
●
●
●
●
● ●●
●
●
●
●●
●●● ●
●●●
●●●●● ●
●
●●
●
●
●
●●
● ●●
●
●
●
●
●
●
●
●
●
●●
● ● ●●
● ●
●
●
●
●
●
●
●●●
●
●
●
●
●
●
●
●
●
●●●●●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●● ●
●●● ●
●●
●●●
●●●
●
● ●
●●●
●
●
●
●
●
●
●● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●● ● ●●
●
●
●
●● ●
●●● ●● ● ● ●● ●
●
●
●
●●
●
●
●●●
●
●
●●
●
●
●●●
●●
●●
●●●
●
●
●
●
●
●● ●●●
● ●●●
●●
● ●●
●
●
● ●●
●
●●●●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
● ● ●● ●
●
●●●
●
●●
●
●
●
●
●●
●
●● ●
●
●
●●●●●
●
●
●
●
●
●
●
●● ● ●●●●
●●●●
●
●●
●
●
●●
●
●●●●
●
●
●
●
● ●●●
●
●● ●
●
●●●
●●
●●
●
●
●
●● ●
●
●
●
●
●
●●
●
●
●●
●●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●● ●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●●● ● ● ●●
●●●●●●
●
●
● ●●● ●
●
●● ●●
●
●●
● ●
●
●
●
●
●
●●
●
●●
●
●
●●●
●
●●
●
●● ●● ●●
●
●
●
●
●
●
●●
●
●
● ● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●●
●
● ●●
●●● ● ● ●
●
●
●
●
●
●
●
●
●
●
●●
●
●●●
●●●
●●
●
●●●
●
●
●
●
●
●
● ●●● ●●
●●
●
●● ●●●●
●● ●
●
●
●
●●
●
●
●
●●●●●
●
●●
●
●●●
●
●
●●
●●
●
●●●●
●
●●●
●
●
●
●
●
●
●
● ●● ●
●●
●
●
●
●
●
●
●●●●
●
●
●
●
●●
●●
●
●
●
●
●
●
●
●●
●
●
●
●
● ● ● ● ● ●●
●
●
●
●
●
●
●
●
●
●● ●● ●●●●● ● ●
● ● ●
●● ●
●●
●
●
●●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●●● ●● ●
● ●●● ● ●
●
● ●
●
●
●
●
●● ●
● ●● ●
●●●●
●● ● ● ●
●●●
●
●
●●●
●
● ●
● ● ●
●
● ●●
●
●●
●
●●
● ●
●●
●
●
●
●
● ● ●● ● ●●
●
●
●●
●
●
●●
●
●
●
●
●●
● ●●
●
● ●
●
●●
●
●
●
●
●
0
5
10
aft
−2
−1
0
1
2
3
●
15
20
25
30
35
Figure 14: WLS weighted residuals and fitted emissions for the confinement
model; data points are colored by house; lowess() curves are shown for each
house.
Dr
maximum excretion rate γ has increased from 1.35 to 2.22 grams per day. Taken
together, these changes lead to essentially unchanged fitted emissions (compare
Figures 13 and 9).
28
2008
aft
0.02
0.00
λt
0.04
ca1bHouse10
2009
0.02
0.00
λt
0.04
ca1bHouse12
2008
2009
0.00
Dr
0.02
λt
0.04
ky1b15
2007
0.02
0.00
λt
0.04
ky1b33
2007
Figure 15: WLS estimated conversion rate for the confinement model; broken
lines indicate days that were omitted in fitting the model.
29
6
Discussion
Dr
aft
The empirical model laid out in Section 3 is based on the variables common to
the data sets collected under the NAEMS program and the Kentucky program,
and necessarily omits other information that might shed light on the chemical
and physical processes involved in ammonia emission. The graphs of observed
and fitted emissions indicate that it can, nevertheless, produce possibly useful
predictions of ammonia emissions, with in-sample residual standard deviation of
less than 4 kg per day per house.
However, the residual plots in Figures 4, 7, 10, and 14 show differences between the California and Kentucky data. The differences suggest that the association of ammonia emissions with temperature and relative humidity is subtly
different between these two parts of the data. Whether the difference is caused by
model error, geography, house layout, or operational details is of course impossible to discern. Additional data collected for other locations or under different
management would be valuable in assessing the merits of the present modeling
approach.
A comparison of the ordinary least squares analysis of Section 5.3 with the
weighted least squares analysis of Section 5.4 suggests that the variables collected
in these data sets are not capable of constraining the parameters of physical interest, principally the rate of deposition of organic nitrogen in manure and the rate
of conversion of manure nitrogen into ammonia. Those parameters would play a
central role in a process-based model. Whether they play a critical role in constructing a robust model for predicting ammonia emissions is less clear.
References
Elwinger, K. and L. Svensson (1996). Effect of dietary protein content, litter and
drinker type on ammonia emission from broiler houses. Journal of Agricultural
Engineering Research 64, 197–208.
Pescatore, A. J., K. D. Casey, and R. S. Gates (2005). Ammonia emissions from
broiler houses. Journal of Applied Poultry Research 14, 635–637.
R Core Team (2012). R: A Language and Environment for Statistical Computing.
Vienna, Austria: R Foundation for Statistical Computing. ISBN 3-900051-070.
30
Southeastern Broiler Gaseous and Particulate Matter Emissions Monitoring Project (2009).
Final project report.
http://www.epa.gov/
airquality/agmonitoring/pdfs/KY1BSummaryReport.pdf.
aft
Zeileis, A. (2004). Econometric computing with hc and hac covariance matrix
estimators. Journal of Statistical Software 11, 1–17.
Dr
Zeileis, A. (2006). Object-oriented computation of sandwich estimators. Journal
of Statistical Software 16, 1–16.
31
A
A.1
R scripts for creating data frames
Combined data
aft
# all.R
#
# Create data frames with the California and Kentucky data,
# and a combined data frame
if (!exists("dataPath"))
dataPath <- "data"
source(file.path(codePath, "ca1b.R"))
source(file.path(codePath, "ky1b.R"))
birdCols
Dr
<- c("House",
"Date",
"FirstDate",
"Birds",
"BirdKg",
"LoadOut",
"DeCake",
"Nh3Kgpd")
weatherCols <- c("ATemp",
"ARH")
envCols
<- c("CTemp",
"CRH",
"AirFlow")
cols <- c(birdCols, weatherCols, envCols)
birdDataCa <- rbind(ca1b("10"), ca1b("12"))
birdDataKy <- rbind(ky1b("15"), ky1b("33"))
birdData
<- rbind(birdDataCa[, cols], birdDataKy[, cols])
rm(birdCols, weatherCols, envCols, cols)
A.2
California data
# ca1b.R
#
# Define the function ca1b(), which creates a data frame
# for one house ("10" or "12") in the California data
source(file.path(codePath, "ca1b-animal.R"))
source(file.path(codePath, "ca1b-nh3.R"))
32
ca1b <- function(house)
{
Animal <- ca1bAnimal()
NH3 <- ca1bNh3()
Env <- ca1bEnv()
Weather <- ca1bWeather()
house, sep = "")
= paste("ca1bHouse", house, sep = ""),
= Animal$Date,
= Animal$Flock,
= Animal$DeCake,
= Animal$LoadOut,
= Animal$FirstDate,
= Animal[[paste(hhouse, "Birds", sep = "")]],
= Animal[[paste(hhouse, "Age", sep = "")]],
= Animal[[paste(hhouse, "BirdKg", sep = "")]],
= NH3[[paste(hhouse, "Nh3Kgpd", sep = "")]],
= Env[[paste(hhouse, "Temp", sep = "")]],
= Env[[paste(hhouse, "RH", sep = "")]],
= Env[[paste(hhouse, "Flow", sep = "")]],
= Weather$Temp,
= Weather$RH,
= Weather$WS,
= Weather$WD,
= Weather$SE,
= Weather$ATM)
Dr
hhouse <- paste("h",
data.frame(House
Date
Flock
DeCake
LoadOut
FirstDate
Birds
Age
BirdKg
Nh3Kgpd
CTemp
CRH
AirFlow
ATemp
ARH
WS
WD
SE
ATM
aft
source(file.path(codePath, "ca1b-env.R"))
source(file.path(codePath, "ca1b-weather.R"))
}
A.2.1
#
#
#
#
#
#
#
Animal data
ca1b-Animal.R
Define the function ca1bAnimal() that reads the CSV File
for the Animal sheet of the California file
(http://www.epa.gov/airquality/agmonitoring/data/
CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met.xls)
and creates a corresponding data frame
ca1bAnimal <function(dataFile =
"CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met-animal.csv")
{
33
aft
File <- file.path(dataPath, dataFile)
Animal <- read.csv(File,
col.names = c("AnimalDay",
"h10Birds",
"h10BirdKg",
"h10BirdKgpm2",
"h12Birds",
"h12BirdKg",
"h12BirdKgpm2"))
a <- Animal$AnimalDay
a <- as.numeric(levels(a))[a]
Animal <- Animal[!is.na(a),]
for (j in c("h10Birds", "h12Birds")) {
a <- as.character(Animal[, j])
a <- sapply(strsplit(a, ","), paste, collapse = "")
a <- as.numeric(a)
a[!is.na(a) & a == 0] <- NA
Animal[, j] <- a
}
Dr
for (j in c("h10BirdKg", "h12BirdKg")) {
a <- Animal[, j]
a <- as.numeric(levels(a))[a]
Animal[, j] <- a
}
firstDate <- as.Date("2007-09-01")
Animal$Date <- firstDate + 0:(nrow(Animal) - 1)
hatchDates <as.Date(c("2007-09-20",
"2007-11-15",
"2008-01-05",
"2008-02-28",
"2008-04-22",
"2008-06-14",
"2008-08-11",
"2008-10-20",
"2008-12-12",
"2009-02-09",
"2009-04-10",
"2009-06-04",
"2009-07-30",
34
"2009-09-26"))
aft
loadOutDates <as.Date(c("2007-08-31", # assume clean litter on day 0
"2007-11-04",
"2008-04-15",
"2008-09-27",
"2009-03-28",
"2009-09-14")) + 1
decakeDates <as.Date(c("2008-01-01",
"2008-02-21",
"2008-06-06",
"2008-08-01",
"2008-12-04",
"2009-01-28",
"2009-05-27",
"2009-07-21")) + 1
Animal$Flock <- cumsum(Animal$Date %in% hatchDates)
Animal$DeCake <- Animal$Date %in% decakeDates
Animal$LoadOut <- Animal$Date %in% loadOutDates
Dr
# we cannot estimate initial litter N because there is a load-out
# before the First emission data
Animal$FirstDate <- FALSE
a <- as.numeric(Animal$Date - c(firstDate, hatchDates)[Animal$Flock + 1])
a[is.na(Animal$h10Birds)] <- NA
a[!is.na(a)] <- a[!is.na(a)] + 1
Animal$h10Age <- a
a <- as.numeric(Animal$Date - c(firstDate, hatchDates)[Animal$Flock + 1])
a[is.na(Animal$h12Birds)] <- NA
a[!is.na(a)] <- a[!is.na(a)] + 1
Animal$h12Age <- a
Animal
}
A.2.2
Emissions data
# ca1b-NH3.R
#
# Define the function ca1bNh3() that reads the CSV File
35
# for the emissions sheet of the California file
# (http://www.epa.gov/airquality/agmonitoring/data/
# CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met.xls)
# and creates a corresponding data frame
aft
ca1bNh3 <- function(dataFile =
"CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met-nh3.csv")
{
File <- file.path(dataPath, dataFile)
NH3 <- read.csv(File,
col.names = c("NH3Day",
"h10Nh3Kgpd",
"h10Nh3Kgpdsd",
"h10Nh3Gpdpm2", "h10Nh3Gpdpm2sd",
"h10Nh3Mgpdph", "h10Nh3Mgpdphsd",
"h10Nh3Gpdpa", "h10Nh3Gpdpasd",
"h12Nh3Kgpd",
"h12Nh3Kgpdsd",
"h12Nh3Gpdpm2", "h12Nh3Gpdpm2sd",
"h12Nh3Mgpdph", "h12Nh3Mgpdphsd",
"h12Nh3Gpdpa", "h12Nh3Gpdpasd"))
a <- NH3$NH3Day
a <- as.numeric(levels(a))[a]
NH3 <- NH3[!is.na(a),]
Dr
for (j in seq(from = 2, to = ncol(NH3), by = 2)) {
a <- NH3[, j]
NH3[, j] <- as.numeric(levels(a))[a]
}
for (j in seq(from = 3, to = ncol(NH3), by = 2)) {
a <- as.character(NH3[, j])
a <- substr(a, 2, nchar(a) - 1)
NH3[, j] <- as.numeric(a)
}
NH3
}
A.2.3
#
#
#
#
#
#
House environment data
ca1b-Env.R
Define the function ca1bEnv() that reads the CSV File
for the environment sheet of the California file
(http://www.epa.gov/airquality/agmonitoring/data/
CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met.xls)
36
# and creates a corresponding data frame
aft
ca1bEnv <- function(dataFile =
"CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met-env.csv")
{
File <- file.path(dataPath, dataFile)
Env <- read.csv(File,
col.names = c("EnvDay",
"h10Temp",
"h10TempSd",
"h10RH",
"h10RHSd",
"h10DeltaP", "h10DeltaPSd",
"h10Flow",
"h10FlowSd",
"h12Temp",
"h12TempSd",
"h12RH",
"h12RHSd",
"h12DeltaP", "h12DeltaPSd",
"h12Flow",
"h12FlowSd"))
a <- Env$EnvDay
a <- as.numeric(levels(a))[a]
Env <- Env[!is.na(a),]
Dr
for (j in 2:ncol(Env)) {
a <- Env[, j]
Env[, j] <- as.numeric(levels(a))[a]
}
Env
}
A.2.4
#
#
#
#
#
#
#
Weather data
ca1b-Weather.R
Define the function ca1bNh3() that reads the CSV File
for the weather sheet of the California file
(http://www.epa.gov/airquality/agmonitoring/data/
CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met.xls)
and creates a corresponding data frame
ca1bWeather <- function(dataFile =
"CA1B_Daily_Mean_Tables_Concentrations_Emissions_Met-weather.csv")
{
File <- file.path(dataPath, dataFile)
Weather <- read.csv(File, skip = 2,
col.names = c("WeatherDay",
"Temp", "TempSd",
37
"RHSd",
"WSSd",
"WDSd",
"SESd",
"ATMSd"))
aft
"RH",
"WS",
"WD",
"SE",
"ATM",
a <- Weather$WeatherDay
a <- as.numeric(levels(a))[a]
Weather <- Weather[!is.na(a),]
for (j in seq(from = 2, to = ncol(Weather), by = 2)) {
a <- Weather[, j]
Weather[, j] <- as.numeric(levels(a))[a]
}
for (j in seq(from = 3, to = ncol(Weather), by = 2)) {
a <- as.character(Weather[, j])
a <- substr(a, 2, nchar(a) - 1)
Weather[, j] <- as.numeric(a)
}
Weather
}
Kentucky data
Dr
A.3
#
#
#
#
#
#
ky1b.R
Define the function ky1b() that reads the CSV File
for the Kentucky spreadsheet
(http://www.epa.gov/airquality/agmonitoring/data/KY1BTysonhumidity.xls)
and creates the data frame for one house ("15" or "33")
ky1b <- function(house)
{
Mass <- function(pounds) (pounds * 0.453592)
Temperature <- function(fahrenheit) ((fahrenheit - 32) * 5/9)
Flow <- function(cfm) (cfm * (2.54 * 12 / 100)ˆ3 / 60)
loadOutDates <- list("15" = "08/26/2006",
"33" = "02/03/2007")[[house]]
deCakeDates <- list("15" = c("04/05/2006",
"06/10/2006",
"10/26/2006",
"01/10/2007"),
38
"33" = c("04/11/2006",
"07/12/2006",
"09/20/2006",
"11/28/2006"))[[house]]
aft
File <- file.path(dataPath, paste("KY1BTysonhumidity-", house, ".csv",
sep = ""))
kt <- read.csv(File, skip = 1)
a <- as.character(kt$Bird..)
a <- sapply(strsplit(a, ","), paste, collapse = "")
kt$Bird.. <- as.numeric(a)
kt$Date <- as.Date(kt$Date, "%d-%b-%y")
ktDecakeDates <- as.Date(deCakeDates, "%m/%d/%Y")
ktLoadoutDates <- as.Date(loadOutDates, "%m/%d/%Y")
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
paste("ky1b", house, sep = ""),
kt$Date,
NA,
kt$Date %in% ktDecakeDates,
kt$Date %in% ktLoadoutDates,
kt$Date == kt$Date[1],
kt$Bird..,
as.numeric(levels(kt$Bird.age..d))[kt$Bird.age..d],
Mass(kt$Bird.Weight..lb.bird),
Mass(kt$NH3..lb),
Temperature(kt$SW.1.oF),
kt$T..,
Flow(kt$Ventilation.rate..cfm.house..daily.mean.),
Temperature(kt$Outside.Temp..oF..Daily.mean.),
kt$Outside.RH.....Daily.mean.,
NA,
NA,
NA,
NA)
Dr
data.frame(House
Date
Flock
DeCake
LoadOut
FirstDate
Birds
Age
BirdKg
Nh3Kgpd
CTemp
CRH
AirFlow
ATemp
ARH
WS
WD
SE
ATM
}
B
B.1
R scripts for model fitting
The emission function
# emit.R
39
#
# define the emission functions
aft
depFunc <- function(x, grams, theta, k) {
(grams / 1000) * ((x/theta) * exp(1 - (x/theta)))ˆk
}
lambdaFunc <- function(param, birdData) {
center <- function(x) {
x <- x - mean(x, na.rm = TRUE)
# uncomment the following line to fit standardized
# coefficients
#
x <- x / sd(x, na.rm = TRUE)
x[is.na(x)] <- 0
x
}
logLambda <- rep(param["b0"], nrow(birdData))
for (n in intersect(names(param), names(birdData)))
logLambda <- logLambda + param[n] * center(birdData[[n]])
exp(logLambda)
}
Dr
emitFunc <- function(param, birdData,
Gam
= param["Gam"],
theta
= param["theta"],
k
= param["k"],
psi
= param["psi"],
firstKy1b15 = param["firstKy1b15"],
firstKy1b33 = param["firstKy1b33"]) {
e <- l <- rep(0, nrow(birdData))
d <- birdData$Birds * depFunc(birdData$BirdKg, Gam, theta, k)
lambda <- lambdaFunc(param, birdData)
for (i in 1:length(l)) {
if (birdData$FirstDate[i]) {
if (birdData$House[i] == "ky1b15")
l[i] <- firstKy1b15
else if (birdData$House[i] == "ky1b33")
l[i] <- firstKy1b33
else stop("Bad birdData$House:", birdData$House[i]);
} else if (birdData$LoadOut[i]) {
l[i] <- 0
} else if (i > 1) {
l[i] <- l[i-1] - e[i-1]
}
40
if (birdData$DeCake[i])
l[i] <- l[i] * psi
if (!is.na(d[i]))
l[i] <- l[i] + d[i]
e[i] <- lambda[i] * l[i]
aft
}
e
}
B.2
The inventory model
# all-nls.R
#
# fit the inventory model by ordinary least squares, using nls()
# and pass the result to fitSummary()
if (!exists("codePath"))
codePath <- "R-code"
source(file.path(codePath, "all.R"))
source(file.path(codePath, "emit.R"))
source(file.path(codePath, "fit-summary.R"))
Dr
birdDataOk <- !(is.na(birdData$Nh3Kgpd) |
is.na(birdData$Birds)
|
is.na(birdData$BirdKg))
birdDataNls <nls(Nh3Kgpd ˜ emitFunc(c(b0 = b0), birdData, Gam, theta, k,
psi, firstKy1b15, firstKy1b33)[birdDataOk],
birdData[birdDataOk,],
start = c(b0
= -3,
Gam
= 1,
theta
= 1.5,
k
= 2,
psi
= 0.75,
firstKy1b15 = 100,
firstKy1b33 = 100))
fitSummary(birdData, birdDataNls, birdDataOk, "inv")
B.3
The full model
# all-full-nls.R
#
# fit the full model by ordinary least squares, using nls()
41
# and pass the result to fitSummary()
aft
if (!exists("codePath"))
codePath <- "R-code"
source(file.path(codePath, "all.R"))
source(file.path(codePath, "emit.R"))
source(file.path(codePath, "fit-summary.R"))
birdDataFullOk <- !(is.na(birdData$Nh3Kgpd)
is.na(birdData$Birds)
is.na(birdData$BirdKg)
is.na(birdData$ATemp)
is.na(birdData$ARH)
is.na(birdData$CTemp)
is.na(birdData$CRH))
|
|
|
|
|
|
Dr
birdDataFullNls <nls(Nh3Kgpd ˜ emitFunc(c(b0
= b0,
ATemp = ATemp,
ARH
= ARH,
CTemp = CTemp,
CRH
= CRH),
birdData, Gam, theta, k, psi,
firstKy1b15, firstKy1b33)[birdDataFullOk],
birdData[birdDataFullOk,],
start = c(b0
= -2.6,
ATemp
= 0.01,
ARH
= 0.01,
CTemp
= 0.01,
CRH
= 0.01,
Gam
= 1.2,
theta
= 1.6,
k
= 1.7,
psi
= 0.7,
firstKy1b15 = 34,
firstKy1b33 = 89))
fitSummary(birdData, birdDataFullNls, birdDataFullOk, "full")
B.4
The confinement model
# all-con-nls.R
#
# fit the confinement model by ordinary least squares, using nls()
# and pass the result to fitSummary()
42
aft
if (!exists("codePath"))
codePath <- "R-code"
source(file.path(codePath, "all.R"))
source(file.path(codePath, "emit.R"))
source(file.path(codePath, "fit-summary.R"))
birdDataConOk <- !(is.na(birdData$Nh3Kgpd)
is.na(birdData$Birds)
is.na(birdData$BirdKg)
is.na(birdData$CTemp)
is.na(birdData$CRH))
|
|
|
|
Dr
birdDataConNls <nls(Nh3Kgpd ˜ emitFunc(c(b0
= b0,
CTemp = CTemp,
CRH
= CRH),
birdData,
Gam, theta, k, psi,
firstKy1b15, firstKy1b33)[birdDataConOk],
birdData[birdDataConOk,],
start = c(b0
= -2.6,
CTemp
= 0.2,
CRH
= 0.1,
Gam
= 1.2,
theta
= 1.6,
k
= 1.7,
psi
= 0.7,
firstKy1b15 = 34,
firstKy1b33 = 89))
fitSummary(birdData, birdDataConNls, birdDataConOk, "con")
B.5
WLS fit of the confinement model
# all-con-pl.R
#
# fit the confinement model by weighted least squares, using gls-PL
# and pass the result to fitSummary()
if (!exists("codePath"))
codePath <- "R-code"
source(file.path(codePath, "all.R"))
source(file.path(codePath, "emit.R"))
source(file.path(codePath, "fit-summary.R"))
43
start <- c(b0
CTemp
CRH
Gam
theta
k
psi
firstKy1b15
firstKy1b33
kappa <- 0.5
|
|
|
|
aft
birdDataConOk <- !(is.na(birdData$Nh3Kgpd)
is.na(birdData$Birds)
is.na(birdData$BirdKg)
is.na(birdData$CTemp)
is.na(birdData$CRH))
= -2.6,
= 0.2,
= 0.1,
= 1.2,
= 1.6,
= 1.7,
= 0.7,
= 34,
= 89)
weights <- rep(1, sum(birdDataConOk))
Dr
for (step in 1:100) {
cat("step", step, "\n")
birdDataConWls <nls(Nh3Kgpd ˜ emitFunc(c(b0
= b0,
CTemp = CTemp,
CRH
= CRH),
birdData, Gam, theta, k, psi,
firstKy1b15, firstKy1b33)[birdDataConOk],
birdData[birdDataConOk,],
start = start, weights = weights)
if (sum(abs(coefficients(birdDataConWls) - start)) < 1e-8 * sum(abs(start)))
break
start <- coefficients(birdDataConWls)
r <- residuals(birdDataConWls)
f <- fitted(birdDataConWls)
names(kappa) <- NULL # not sure why this is needed, but it is...
birdDataConWlsVar <nls(rˆ2 ˜ sigmaˆ2 * (f ˆ kappa)ˆ2,
start = c(sigma = sd(r * sqrt(weights)), kappa = kappa),
weights = weightsˆ2)
kappa <- coefficients(birdDataConWlsVar)["kappa"]
weights <- (f ˆ kappa)ˆ(-2)
44
}
print(summary(birdDataConWlsVar))
fitSummary(birdData, birdDataConWls, birdDataConOk, "con-pl", "topright")
C
C.1
aft
rm(start, kappa, weights, step, r, f)
R scripts for figures and summaries
Observations
# fig-obs.R
#
# Plot total bird mass and emissions by day
if (!exists ("codePath"))
codePath <- "R-code"
if (!exists ("dataPath"))
dataPath <- "data"
if (!exists ("graphicsPath"))
graphicsPath <- "graphics"
Dr
source(file.path(codePath, "ca1b.R"))
source(file.path(codePath, "ky1b.R"))
figObs <- function(House) {
with(House,
{
total <- Birds * BirdKg / 1000
plot(Date, total, xlab = "", ylab = "Mass (1000 kg)",
type = "n", ylim = c(0, 70), main = House[1])
ok <- !is.na(Nh3Kgpd)
y <- z <- total
y[!ok] <- NA
z[ok] <- NA
matlines(Date, cbind(y, z), col = "red", lty = 1:2)
par(new = TRUE)
plot(Date, Nh3Kgpd, type = "n", axes = FALSE,
xlab = "", ylab = "", ylim = c(0, 35))
ok <- !is.na(total)
y <- z <- Nh3Kgpd
45
y[!ok] <- NA
z[ok] <- NA
matlines(Date, cbind(y, z), col = "blue", lty = 1:2)
aft
axis(4)
mtext(expression(NH[3] ˜ " (kg/day)"),
side = 4, line = 3, cex = 0.7)
abline(v = Date[LoadOut], col = "green")
}
)
}
pdf(file.path(graphicsPath, "fig-obs.pdf"), width = 6, height = 6.5)
par(mfcol = c(4, 1), mar = c(2, 4, 2, 4) + 0.1)
figObs(ca1b("10"))
figObs(ca1b("12"))
figObs(ky1b("15"))
figObs(ky1b("33"))
dev.off()
C.2
Deposition functions
Dr
# fig-dep.R
#
# Plot N excretion per bird, by mass
figDep <- function(birdData, param) {
x <- range(birdData$BirdKg, na.rm = TRUE)
x <- seq(from = x[1], to = x[2], len = 100)
plot(x, 1000 * depFunc(x, param["Gam"], param["theta"], param["k"]),
type = "l", xlab = "Average bird mass, kg/b",
ylab = "Nitrogen excretion, g/(bd)")
}
C.3
Residual plots
# fig-resid.R
#
# Plot residuals versus fitted values
figResid <- function(birdData, N, where)
{
f <- fitted(N)
r <- residuals(N)
if (!is.null(N$weights))
46
r <- r * sqrt(N$weights)
u <- unique(birdData$House)
plot(f, r, xlab = "", ylab = "", col = match(birdData$House, u))
legend(where, leg = u, col = 1:length(u), pch = 1)
}
C.4
#
#
#
#
#
#
Correlation plots
fig-corr.R
aft
fSplit <- split(f, birdData$House)
rSplit <- split(r, birdData$House)
for (j in 1:length(fSplit))
if (length(fSplit[[j]]) > 0)
lines(lowess(fSplit[[j]], rSplit[[j]], f = 0.5), col = j)
functions for plotting ACFs and CCFs
we use the usual sum of lagged products, but summed only over the
available lags, by replacing unavailable values by 0
Dr
acfPlot <- function(x, xDate = 1:length(x), m) {
x <- x - mean(x)
r <- range(xDate)
d <- r[1] + 0:diff(r)
xFill <- rep(0, length(d))
xFill[match(xDate, d)] <- x
a <- acf(xFill, main = m)
cat("Autocorrelations of", m, "\n")
print(cbind(Lag = a$lag, ACF = a$ac))
}
ccfPlot <- function(x, y, xDate = 1:length(x), yDate = 1:length(y), m) {
x <- x - mean(x)
y <- y - mean(y)
r <- range(c(xDate, yDate))
d <- r[1] + 0:diff(r)
xFill <- yFill <- rep(0, length(d))
xFill[match(xDate, d)] <- x
yFill[match(yDate, d)] <- y
a <- ccf(xFill, yFill, main = m)
cat("Cross correlations of", m, "\n")
print(cbind(Lag = a$lag, CCF = a$ac))
}
47
C.5
fit-summary.R
summarize the result of fitting a model
prints robust standard errors on the console
and produces various graphs
aft
#
#
#
#
#
Summaries
source(file.path(codePath, "fig-dep.R"))
source(file.path(codePath, "fig-resid.R"))
source(file.path(codePath, "fig-corr.R"))
if (!exists ("graphicsPath"))
graphicsPath <- "graphics"
fitSummary <- function(birdData, N, ok, prefix, where = "bottomleft") {
print(summary(N))
cat("AIC:", AIC(N), "; BIC:", AIC(N, k = log(length(N$m$resid()))), "\n")
# alternative summaries
Dr
X <- N$m$gradient()
if (!is.null(N$weights))
X <- X / sqrt(N$weights)
cN <- coefficients(N)
dimnames(X)[[2]] <- names(cN)
y <- N$m$lhs()
yhat <- N$m$fitted()
l <- lm(y ˜ 0 + offset(yhat) + X)
l$coefficients <- cN
library(sandwich);
b <- bread(l) / length(y)
m <- meat(l)
m[] <- 0
XSplit <- split(data.frame(X), birdData$House[ok])
ySplit <- split(y, birdData$House[ok])
yhatSplit <- split(yhat, birdData$House[ok])
lmj <- function(y, yhat, X) lm(y ˜ 0 + offset(yhat) + X)
for (j in 1:length(XSplit)) {
Xj <- as.matrix(XSplit[[j]])
if (nrow(Xj) == 0)
next
dimnames(Xj)[[2]] <- names(cN)
yj <- ySplit[[j]]
48
}
aft
yhatj <- yhatSplit[[j]]
lj <- lmj(yj, yhatj, Xj)
mj <- meatHAC(lj)
i <- match(dimnames(mj)[[2]], dimnames(m)[[2]])
m[i, i] <- m[i, i] + length(yj) * mj
Dr
dateOkSplit <- split(birdData$Date[ok], birdData$House[ok])
j10 <- match("ca1bHouse10", names(XSplit))
j12 <- match("ca1bHouse12", names(XSplit))
if (!is.na(j10) && !is.na(j12)) {
ok10 <- dateOkSplit[[j10]] %in% dateOkSplit[[j12]]
ok12 <- dateOkSplit[[j12]] %in% dateOkSplit[[j10]]
y10 <- ySplit[[j10]][ok10]
y12 <- ySplit[[j12]][ok12]
yhat10 <- yhatSplit[[j10]][ok10]
yhat12 <- yhatSplit[[j12]][ok12]
X10 <- as.matrix(XSplit[[j10]])[ok10, ]
dimnames(X10)[[2]] <- names(cN)
X12 <- as.matrix(XSplit[[j12]])[ok12, ]
dimnames(X12)[[2]] <- names(cN)
mss <- meatHAC(lmj(y10 + y12, yhat10 + yhat12, X10 + X12))
msd <- meatHAC(lmj(y10 + y12, yhat10 + yhat12, X10 - X12))
mds <- meatHAC(lmj(y10 - y12, yhat10 - yhat12, X10 + X12))
mdd <- meatHAC(lmj(y10 - y12, yhat10 - yhat12, X10 - X12))
i <- match(dimnames(mss)[[2]], dimnames(m)[[2]])
m[i, i] <- m[i, i] + length(y10) * (mss - msd - mds + mdd) / 8
}
l.Cov <- b %*% m %*% b
l.Std <- sqrt(diag(l.Cov));
l.Rat <- coefficients(l)/l.Std
l.est <- cbind(’Estimate’
’Std. Error’
’t value’
’Pr(>|t|)’
=
=
=
=
coefficients(l),
l.Std,
l.Rat,
2 * pt(abs(l.Rat), l$df.residual,
lower.tail = FALSE))
dimnames(l.est)[[1]] <- names(coefficients(l));
cat("\nModified robust (sandwich) standard errors:\n\n");
printCoefmat(l.est, digits = 4);
# graphs
f <- g <- emitFunc(coefficients(N), birdData)
49
f[!ok] <- NA
g[ok] <- NA
aft
nf <- ng <- birdData$Nh3Kgpd
nf[!ok] <- NA
ng[ok] <- NA
dateSplit <- split(birdData$Date, birdData$House)
fgSplit <- split(data.frame(cbind(f, g, nf, ng)), birdData$House)
# observed and fitted NH3:
pdf(file.path(graphicsPath, paste(prefix, "fit.pdf", sep = "-")),
width = 6, height = 6.5)
par(mfcol = c(length(dateSplit), 1), mar = c(2, 4, 2, 4) + 0.1)
Dr
for (j in 1:length(dateSplit)) {
x <- dateSplit[[j]]
plot(x, fgSplit[[j]][,1], type = "n", xlab = "",
ylab = expression(NH[3] ˜ " (kg/day)"), ylim = c(0, 35))
matlines(x, fgSplit[[j]], lty = c(1, 2, 1, 2),
col = c("black", "black", "blue", "blue"))
if (length(dateSplit) > 1)
title(names(dateSplit)[j])
}
if (length(dateSplit) == 1) {
title(substitute(birdData))
legend("topleft", leg = c("Fitted", "Predicted", "Observed"),
col = c("black", "blue", "red"), lty = c(1, 2, 1))
}
dev.off()
# N excretion per bird, by mass
pdf(file.path(graphicsPath, paste(prefix, "dep.pdf", sep = "-")),
width = 4, height = 2.75, pointsize = 10)
par(mar = c(5, 4, 1, 1) + 0.1)
figDep(birdData, cN)
dev.off()
# Conversion rate to NH3
lambda <- lambdaFunc(coefficients(N), birdData)
if (diff(range(lambda)) > 0) {
pdf(file.path(graphicsPath, paste(prefix, "conv.pdf", sep = "-")),
width = 6, height = 6.5)
par(mfcol = c(length(dateSplit), 1), mar = c(2, 4, 2, 4) + 0.1)
50
}
aft
l <- m <- lambda
l[!ok] <- NA
m[ok] <- NA
lmSplit <- split(data.frame(cbind(l, m)), birdData$House)
for (j in 1:length(dateSplit)) {
x <- dateSplit[[j]]
plot(x, lmSplit[[j]][,1], type = "n",
ylim = c(0, max(lambda, na.rm = TRUE)),
xlab = "", ylab = expression(lambda[t]))
matlines(x, lmSplit[[j]],
col = rep("black", 2), lty = 1:2)
if (length(dateSplit) > 1)
title(names(dateSplit)[j])
}
dev.off()
# residuals vs fitted
pdf(file.path(graphicsPath, paste(prefix, "resid.pdf", sep = "-")),
width = 5, height = 2.5, pointsize = 10)
par(mar = c(2, 2, 0, 1) + 0.1)
figResid(birdData[ok, ], N, where)
dev.off()
Dr
# residual correlations
r <- residuals(N)
if (!is.null(N$weights))
r <- r * sqrt(N$weights)
rSplit <- split(r, birdData$House[ok]);
pdf(file.path(graphicsPath, paste(prefix, "acf.pdf", sep = "-")),
width = 6, height = 6.5)
par(mfcol = c(2, length(dateOkSplit) / 2))
for (house in names(rSplit))
acfPlot(rSplit[[house]], dateOkSplit[[house]], house)
dev.off()
if (!is.na(j10) && !is.na(j12)) {
pdf(file.path(graphicsPath, paste(prefix, "ccf.pdf", sep = "-")),
width = 5, height = 2.5, pointsize = 10)
par(mar = c(2, 4, 3, 1) + 0.1)
ccfPlot(rSplit[[j10]], rSplit[[j12]],
dateOkSplit[[j10]], dateOkSplit[[j12]],
"ca1bHouse10 & ca1bHouse12")
dev.off()
51
Dr
aft
}
}
52