Area Change Estimation¶
Estimate annual changes in forest land area using remeasured plots.
Overview¶
The area_change() function calculates net and gross changes in forest land area by tracking land use transitions between measurement periods. This uses the SUBP_COND_CHNG_MTRX table which records subplot condition changes.
import pyfia
db = pyfia.FIA("georgia.duckdb")
db.clip_most_recent()
# Net annual area change
net_change = pyfia.area_change(db)
# Gross forest loss by ownership
loss_by_owner = pyfia.area_change(db, change_type="gross_loss", grp_by="OWNGRPCD")
Function Reference¶
area_change
¶
area_change(db: FIA, land_type: Literal['forest', 'timber'] = 'forest', change_type: Literal['net', 'gross_gain', 'gross_loss'] = 'net', annual: bool = True, grp_by: Optional[Union[str, List[str]]] = None, area_domain: Optional[str] = None, variance: bool = False, totals: bool = False) -> DataFrame
Estimate area change for forest or timberland.
Calculates net or gross change in forest/timberland area using remeasured plots from the SUBP_COND_CHNG_MTRX table. Only plots measured at two time points contribute to the estimate.
| PARAMETER | DESCRIPTION |
|---|---|
db
|
FIA database connection with EVALID set
TYPE:
|
land_type
|
Land classification to track changes for: - 'forest': All forest land (COND_STATUS_CD = 1) - 'timber': Timberland only (productive, unreserved forest)
TYPE:
|
change_type
|
Type of change to calculate: - 'net': Net change (gains minus losses) - 'gross_gain': Only area gained (non-forest to forest) - 'gross_loss': Only area lost (forest to non-forest)
TYPE:
|
annual
|
If True, return annualized rate in acres/year If False, return total change over remeasurement period
TYPE:
|
grp_by
|
Column(s) to group results by (e.g., 'OWNGRPCD', 'FORTYPCD')
TYPE:
|
area_domain
|
SQL-like filter expression for conditions
TYPE:
|
variance
|
Whether to calculate sampling variance and standard error
TYPE:
|
totals
|
Whether to include totals row
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DataFrame
|
Area change estimates with columns: - STATECD: State FIPS code - AREA_CHANGE_TOTAL: Area change (acres/year if annual=True, else acres) - N_PLOTS: Number of remeasured plots - SE: Standard error (if variance=True) - VARIANCE: Sampling variance (if variance=True) - Grouping columns (if grp_by specified) |
Examples:
>>> from pyfia import FIA, area_change
>>> with FIA("path/to/db.duckdb") as db:
... db.clip_most_recent()
... # Net annual forest area change
... result = area_change(db, land_type="forest")
... print(f"Annual change: {result['AREA_CHANGE_TOTAL'][0]:+,.0f} acres/year")
>>> # Gross forest loss by ownership
>>> result = area_change(
... db,
... change_type="gross_loss",
... grp_by="OWNGRPCD",
... variance=True
... )
Notes
Area change estimation requires remeasured plots (plots with both current and previous measurements). States with newer FIA programs may have fewer remeasured plots, resulting in higher sampling errors.
The REMPER (remeasurement period) varies by plot but averages approximately 5-7 years in most states.
References
Bechtold & Patterson (2005), "The Enhanced Forest Inventory and Analysis Program - National Sampling Design and Estimation Procedures", Chapter 4.
Source code in src/pyfia/estimation/estimators/area_change.py
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | |
Change Types¶
| Type | Description |
|---|---|
"net" |
Net change = (gains from non-forest) - (losses to non-forest) |
"gross_gain" |
Area converted from non-forest to forest |
"gross_loss" |
Area converted from forest to non-forest |
Technical Notes¶
Data Requirements¶
Area change estimation requires remeasured plots:
SUBP_COND_CHNG_MTRXtable tracks subplot-level condition changesCONDtable provides current and previous condition statusPLOTtable providesREMPER(remeasurement period)- Only plots measured at two time points contribute to estimates
Condition Status Codes¶
| COND_STATUS_CD | Description |
|---|---|
| 1 | Forest land |
| 2 | Non-forest land |
| 3 | Non-census water |
| 4 | Census water |
| 5 | Denied access |
Transition Logic¶
- Gain: Previous
COND_STATUS_CD != 1, CurrentCOND_STATUS_CD == 1 - Loss: Previous
COND_STATUS_CD == 1, CurrentCOND_STATUS_CD != 1 - Net: Gains minus losses
Annualization¶
By default, results are annualized by dividing by REMPER (remeasurement period, typically 5-7 years). Set annual=False to get total change over the measurement period.
Examples¶
Net Annual Forest Area Change¶
result = pyfia.area_change(db, land_type="forest")
net = result["AREA_CHANGE_TOTAL"][0]
print(f"Annual Net Change: {net:+,.0f} acres/year")
# Positive = net gain, Negative = net loss
Gross Gain and Loss¶
# Area gained (non-forest to forest)
gain = pyfia.area_change(db, change_type="gross_gain")
print(f"Annual Gain: {gain['AREA_CHANGE_TOTAL'][0]:,.0f} acres/year")
# Area lost (forest to non-forest)
loss = pyfia.area_change(db, change_type="gross_loss")
print(f"Annual Loss: {loss['AREA_CHANGE_TOTAL'][0]:,.0f} acres/year")
# Verify: net = gain - loss
net = pyfia.area_change(db, change_type="net")
assert abs(net["AREA_CHANGE_TOTAL"][0] - (gain["AREA_CHANGE_TOTAL"][0] - loss["AREA_CHANGE_TOTAL"][0])) < 1
Total Change (Non-Annualized)¶
# Total change over remeasurement period (not per year)
result = pyfia.area_change(db, annual=False)
print(f"Total Change: {result['AREA_CHANGE_TOTAL'][0]:+,.0f} acres")
Area Change by Ownership¶
result = pyfia.area_change(
db,
change_type="gross_loss",
grp_by="OWNGRPCD"
)
# OWNGRPCD: 10=Forest Service, 20=Other Federal, 30=State/Local, 40=Private
print(result)
Area Change by Forest Type¶
result = pyfia.area_change(
db,
grp_by="FORTYPCD"
)
result = pyfia.join_forest_type_names(result, db)
print(result.sort("AREA_CHANGE_TOTAL").head(10)) # Top losers
With Variance Estimation¶
result = pyfia.area_change(
db,
variance=True
)
print(f"Net Change: {result['AREA_CHANGE_TOTAL'][0]:+,.0f} acres/year")
print(f"SE: {result['SE'][0]:,.0f}")
Comparison with EVALIDator¶
EVALIDator provides area change estimates through the following snum codes:
| snum | Description |
|---|---|
| 127 | Forest land area change (remeasured conditions, both measurements) |
| 128 | Forest land area change (at least one measurement is forest) |
| 136 | Annual forest land area change (both measurements forest) |
| 137 | Annual forest land area change (either measurement forest) |
EVALIDator Interpretation
EVALIDator's "area change" estimates (snum 136, 137) report the total area meeting the criteria on remeasured plots, not the net transition. The difference between snum 137 (either) and snum 136 (both) represents the total transition area.
pyFIA's area_change() calculates the net transition (gains minus losses), which is typically what users want for trend analysis.
References¶
- Bechtold & Patterson (2005), "The Enhanced Forest Inventory and Analysis Program - National Sampling Design and Estimation Procedures", Chapter 4
- FIA Database User Guide, SUBP_COND_CHNG_MTRX table documentation