Overview 2025 Data Full

Author

Nino

Basic checks

Code
print("Look at only NA columns")
[1] "Look at only NA columns"
Code
data_2025_complete %>%
  select(where(~ all(is.na(.)))) %>%
  names() 
 [1] "JEZYK"             "M1_PANEL_1"        "M2_PANEL"         
 [4] "M6_PANEL"          "M7_PANEL"          "TEST"             
 [7] "ZRODLO"            "QCombined_podszyt" "QCombined_zreb"   
[10] "QCombined_pow"     "geometry"         
Code
summary(data_2025_complete$duration_min)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
   9.067   14.227   19.479   27.234   29.035 1475.502 
Code
data_2025_complete_filt <- data_2025_complete %>% filter(duration_min <= 3*60)

ggplot(data = data_2025_complete_filt) +
  geom_histogram(aes(x = duration_min), bins = 30, fill = "steelblue", color = "white") +
  labs(x = "Duration (minutes)", y = "Count", title = "Survey Completion Time Distribution") +
  theme_minimal()

Code
attr(data_2025_complete$M3v, "labels")
NULL
Code
ggplot(data = data_2025_complete) +
  geom_boxplot(aes(x = as.factor(M3v), y = duration_min, fill = as.factor(M3v)), outlier.shape = NA) +
  coord_cartesian(ylim = c(0, 45)) +
  labs(x = "Age Group", y = "Duration (minutes)", fill="Age Group", title = "Survey Duration by Age Group") +
  theme_minimal()

Code
ggplot(data = data_2025_complete) +
  geom_boxplot(aes(x = as.factor(WERSJA_A_B), y = duration_min, fill = as.factor(WERSJA_A_B)), outlier.shape = NA) +
  coord_cartesian(ylim = c(0, 45)) +
  labs(x = "Survey version", y = "Duration (minutes)", fill="Survey version", title = "Survey Duration by Version") +
  theme_minimal()

Check Conditions

Code
print("Check A: Drop outs")
[1] "Check A: Drop outs"
Code
# Drop out possibilities:
#   1. N1 == 2
table(data_2025_complete$N1, useNA = "ifany") # 167 drop outs, 161 people surveyed

   1 
2263 
Code
sum(table(data_2025_complete$N1, useNA = "ifany")) # 333 respondents overall
[1] 2263
Code
#   2. NCONTROL (before DCE) =! "Stimme teilweise zu"
table(data_2025_complete$NCONTROL, useNA = "ifany") # no further drop outs

   2 
2263 
Code
#   3. Survey version on drought: A10_99 =! "trifft eher zu" (4)
attr(data_2025_complete$A10_99, "label")
[1] "A10_99. To what extent does perceptible drought damage influence which forest areas you visit? Please rate each statement on a scale from 1 = “strongly disagree” to 5 = “strongly agree”. (... please select “partly agree” for this statement.)"
Code
attr(data_2025_complete$A10_99, "labels")
NULL
Code
table(data_2025_complete$A10_99, useNA = "ifany") # no further drop outs (80 (of 161) people in drought version of the survey)

   4 <NA> 
1106 1157 
Code
# check how many people answer the first drought question (asked in both survey versions) 
attr(data_2025_complete$A1, "label")
[1] "A1. Have the forest areas that you regularly visit changed in the last 10 years?"
Code
attr(data_2025_complete$A1, "labels")
NULL
Code
table(data_2025_complete$A1, useNA = "ifany") # all 161 people

  1   2   3   4 
475 567 781 440 
Code
sum(table(data_2025_complete$A1))
[1] 2263
Code
print("After survey version split 80 people left in survey version on drought")
[1] "After survey version split 80 people left in survey version on drought"
Code
attr(data_2025_complete$A4_1, "label")
[1] "A4_1. How would you rate the impact of drought damage in forests in relation to the following aspects? Please rate each statement on a scale from 1 = “Major problem” to 5 = “Major opportunity”. (… for nature and the environment)"
Code
attr(data_2025_complete$A4_1, "labels")
NULL
Code
table(data_2025_complete$A4_1, useNA = "ifany") # 80 people left in survey version on drought

   1    2    3    4    5 <NA> 
 503  288  139  108   68 1157 
Code
sum(table(data_2025_complete$A4_1))
[1] 1106
Code
# check how many answered the question after the last control question
attr(data_2025_complete$A11, "label")
[1] "A11. Are you concerned about the long-term availability of healthy forests in Germany?"
Code
attr(data_2025_complete$A11, "labels")
NULL
Code
table(data_2025_complete$A11, useNA = "ifany")

   1    2    3    4    5 <NA> 
 302  580  128   71   25 1157 
Code
sum(table(data_2025_complete$A11)) # still all 80 in survey after last control question
[1] 1106
Code
print("Check B: PRE-DCE PART")
[1] "Check B: PRE-DCE PART"
Code
print("1. N2-based branching into either N3-N10 (N2 == 1) or N11-N22 (N2==2)")
[1] "1. N2-based branching into either N3-N10 (N2 == 1) or N11-N22 (N2==2)"
Code
table(data_2025_complete$N2, useNA = "ifany") # 126 Waldbesuch einziges Ziel, 35 respondents Waldbesuch mit anderen Aktivitäten

   1    2 
1708  555 
Code
block_N3_to_N10 <- c("N3_1", "N3_2", "N4_1", "N4_2", "N4_9_none", "N5",
                     paste0("N6_", 1:17), "N6_17_other", "N7_1", "N8_1", "N8_2", "N9", "N10", "N10_5_other")

block_N11_to_N22 <- c("N11", "N11_7_other", "N12_1_1", "N13_1", "N13_2", "N14_1", "N14_2", "N14_9_none", "N15",
                      paste0("N16_", 1:17), "N16_17_other", "N17_1", "N18_1", "N18_2", "N19_1", "N19_2", "N19_9_none",
                      "N20_1", "N21", "N22", "N22_5_other")

# Create Flags for Response in Each Block (TRUE/FALSE)
# data_2025_complete <- data_2025_complete %>%
#   mutate(
#       block1_answered = rowSums(select(., all_of(block_N3_to_N10)) != "" & !is.na(select(., all_of(block_N3_to_N10)))) > 0,
#       block2_answered = rowSums(select(., all_of(block_N11_to_N22)) != "" & !is.na(select(., all_of(block_N11_to_N22)))) > 0
#     )
# 
# # Check Consistency with N2 Routing
# table(data_2025_complete$N2, data_2025_complete$block1_answered, data_2025_complete$block2_answered, useNA = "ifany")
# count(data_2025_complete, N2, block1_answered, block2_answered)

# delete helping vars
# data_2025_complete$block_N3_to_N10 <- NULL
# data_2025_complete$block_N11_to_N22 <- NULL
# data_2025_complete$block1_answered <- NULL
# data_2025_complete$block2_answered <- NULL

print("2. Single, smaller conditions:")
[1] "2. Single, smaller conditions:"
Code
print("2.1: N23: Only shown if N10 or N22 == 3")
[1] "2.1: N23: Only shown if N10 or N22 == 3"
Code
table(data_2025_complete$N10, useNA = "ifany") # N10 == 3

   1    2    3    4    5 <NA> 
 470  241  160  826   11  555 
Code
table(data_2025_complete$N22, useNA = "ifany") # N22 == 3

   1    2    3    4    5 <NA> 
 102   43   49  351   10 1708 
Code
table(data_2025_complete$N23[!(data_2025_complete$N10 == 3 | data_2025_complete$N22 == 3)], useNA = "ifany") # only NA

<NA> 
2054 
Code
count(data_2025_complete, N2, N23, N10, N22)
Simple feature collection with 12 features and 5 fields
Geometry type: MULTIPOINT
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 12 × 6
      N2   N23   N10   N22     n                                        geometry
 * <dbl> <dbl> <dbl> <dbl> <int>                                <MULTIPOINT [°]>
 1     1     1     3    NA   121 ((-1.858765 43.34529), (14.91314 51.06825), (1…
 2     1     2     3    NA    39 ((24.63728 59.43429), (14.06135 50.96921), (7.…
 3     1    NA     1    NA   470 ((13.82951 51.24481), (14.38537 51.20632), (14…
 4     1    NA     2    NA   241 ((-4.148713 33.64863), (14.32302 52.28856), (1…
 5     1    NA     4    NA   826 ((6.328122 33.43144), (6.328119 33.43144), (6.…
 6     1    NA     5    NA    11 ((12.50725 48.36338), (8.274078 48.94866), (10…
 7     2     1    NA     3    37 ((13.94376 51.98044), (8.230844 48.12858), (8.…
 8     2     2    NA     3    12 ((13.97896 50.638), (13.6734 50.99489), (8.130…
 9     2    NA    NA     1   102 ((14.39528 52.39488), (14.41544 51.17283), (14…
10     2    NA    NA     2    43 ((14.38356 51.72751), (13.343 49.01588), (9.26…
11     2    NA    NA     4   351 ((32.91229 46.0284), (8.255586 55.65127), (15.…
12     2    NA    NA     5    10 ((24.42833 61.03705), (15.04955 44.82084), (13…
Code
print("2.2: N23a: Only if N23 == 2 (Nein)")
[1] "2.2: N23a: Only if N23 == 2 (Nein)"
Code
table(data_2025_complete$N23a_1[data_2025_complete$N23 != 2], useNA = "ifany")

<NA> 
2212 
Code
count(data_2025_complete, N2, N23, N23a_1)
Simple feature collection with 36 features and 4 fields
Geometry type: GEOMETRY
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 36 × 5
      N2   N23 N23a_1     n                                             geometry
 * <dbl> <dbl>  <dbl> <int>                                       <GEOMETRY [°]>
 1     1     1     NA   121 MULTIPOINT ((-1.858765 43.34529), (14.91314 51.0682…
 2     1     2      2     1                            POINT (24.63728 59.43429)
 3     1     2      3     7 MULTIPOINT ((12.39883 51.30082), (13.27366 52.60907…
 4     1     2      4     3 MULTIPOINT ((9.942627 49.7881), (7.140427 51.53134)…
 5     1     2      5     3 MULTIPOINT ((11.45253 48.03599), (11.5342 48.88714)…
 6     1     2      6     2 MULTIPOINT ((7.121908 49.27408), (11.90379 48.11608…
 7     1     2      7     4 MULTIPOINT ((12.36056 51.32911), (12.36048 51.29381…
 8     1     2      8     1                            POINT (10.13542 53.70239)
 9     1     2      9     2 MULTIPOINT ((14.06135 50.96921), (11.5396 52.33596))
10     1     2     10     2 MULTIPOINT ((9.127526 48.76064), (9.884771 53.44534…
# ℹ 26 more rows
Code
print("2.3: N24: Only if N10 or N22 == 4 (car)")
[1] "2.3: N24: Only if N10 or N22 == 4 (car)"
Code
table(data_2025_complete$N24_1[!(data_2025_complete$N10 == 4 | data_2025_complete$N22 == 4)], useNA = "ifany")

<NA> 
1086 
Code
count(data_2025_complete, N2, N24_1, N10, N22)
Simple feature collection with 25 features and 5 fields
Geometry type: GEOMETRY
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 25 × 6
      N2 N24_1   N10   N22     n                                        geometry
 * <dbl> <dbl> <dbl> <dbl> <int>                                  <GEOMETRY [°]>
 1     1     1     4    NA   366 MULTIPOINT ((9.519691 55.50398), (15.53532 52.…
 2     1     2     4    NA   195 MULTIPOINT ((14.45093 52.21537), (14.04597 51.…
 3     1     3     4    NA   163 MULTIPOINT ((33.1082 40.97438), (8.173572 55.8…
 4     1     4     4    NA    56 MULTIPOINT ((6.328122 33.43144), (6.328119 33.…
 5     1     5     4    NA    18 MULTIPOINT ((13.38636 48.72506), (9.646683 48.…
 6     1     6     4    NA     2 MULTIPOINT ((9.731483 50.76513), (7.110043 50.…
 7     1    20     4    NA     1                        POINT (7.78862 49.23879)
 8     1    30     4    NA     1                       POINT (7.465897 51.34045)
 9     1    NA     1    NA   470 MULTIPOINT ((13.82951 51.24481), (14.38537 51.…
10     1    NA     2    NA   241 MULTIPOINT ((-4.148713 33.64863), (14.32302 52…
# ℹ 15 more rows
Code
print("2.4: N25: only if N10 or N22 == 4")
[1] "2.4: N25: only if N10 or N22 == 4"
Code
table(data_2025_complete$N25[!(data_2025_complete$N10 == 4 | data_2025_complete$N22 == 4)], useNA = "ifany")

<NA> 
1086 
Code
count(data_2025_complete, N2, N25, N25_1_other, N10, N22)
Simple feature collection with 147 features and 6 fields
Geometry type: GEOMETRY
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 147 × 7
      N2   N25 N25_1_other   N10   N22     n                            geometry
 * <dbl> <dbl> <chr>       <dbl> <dbl> <int>                      <GEOMETRY [°]>
 1     1     1 0               4    NA     2 MULTIPOINT ((9.105253 48.75908), (…
 2     1     1 0.9             4    NA     1           POINT (9.923058 51.02885)
 3     1     1 10              4    NA    19 MULTIPOINT ((8.173572 55.85895), (…
 4     1     1 10.6            4    NA     1           POINT (11.71898 47.80159)
 5     1     1 100             4    NA     1           POINT (10.58964 50.59304)
 6     1     1 11              4    NA    18 MULTIPOINT ((8.376389 49.61469), (…
 7     1     1 12              4    NA    20 MULTIPOINT ((6.8389 49.30901), (11…
 8     1     1 12L/100KM       4    NA     1           POINT (10.08425 50.99798)
 9     1     1 12l /100km      4    NA     1           POINT (13.24781 53.67683)
10     1     1 13              4    NA     4 MULTIPOINT ((9.706378 50.18075), (…
# ℹ 137 more rows
Code
print("2.5: N26: Only if N25 == 2 (Nein)")
[1] "2.5: N26: Only if N25 == 2 (Nein)"
Code
table(data_2025_complete$N26[data_2025_complete$N25 != 2], useNA = "ifany")

<NA> 
1772 
Code
count(data_2025_complete, N2, N26, N25)
Simple feature collection with 16 features and 4 fields
Geometry type: GEOMETRY
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 16 × 5
      N2   N26   N25     n                                              geometry
 * <dbl> <dbl> <dbl> <int>                                        <GEOMETRY [°]>
 1     1     1     2     6 MULTIPOINT ((10.88711 51.21785), (10.27982 51.03958)…
 2     1     2     2    49 MULTIPOINT ((8.735011 48.01632), (8.12542 49.45997),…
 3     1     3     2   121 MULTIPOINT ((13.8101 51.09987), (13.54965 50.96636),…
 4     1     4     2   116 MULTIPOINT ((13.87093 51.08502), (13.11577 49.12121)…
 5     1     5     2    36 MULTIPOINT ((33.1082 40.97438), (13.38636 48.72506),…
 6     1     6     2     8 MULTIPOINT ((14.45093 52.21537), (12.9886 47.64051),…
 7     1    NA     1   490 MULTIPOINT ((6.328122 33.43144), (6.328119 33.43144)…
 8     1    NA    NA   882 MULTIPOINT ((-1.858765 43.34529), (-4.148713 33.6486…
 9     2     1     2     1                             POINT (11.38076 50.60307)
10     2     2     2    14 MULTIPOINT ((13.10249 49.07096), (12.29266 48.07879)…
11     2     3     2    59 MULTIPOINT ((14.44239 51.45998), (15.64847 47.96004)…
12     2     4     2    52 MULTIPOINT ((13.61755 51.14482), (19.40598 49.16058)…
13     2     5     2    26 MULTIPOINT ((13.45001 48.80996), (12.38986 47.81178)…
14     2     6     2     3 MULTIPOINT ((14.44994 52.21486), (10.00477 50.94959)…
15     2    NA     1   196 MULTIPOINT ((32.91229 46.0284), (8.255586 55.65127),…
16     2    NA    NA   204 MULTIPOINT ((24.42833 61.03705), (14.39528 52.39488)…
Code
print("2.6: N29–N32 if N28 == 1")
[1] "2.6: N29–N32 if N28 == 1"
Code
attr(data_2025_complete$N28, "label")
[1] "N28. Was your overall trip that included the forest visit longer or shorter than 1 day?"
Code
attr(data_2025_complete$N28, "labels")
NULL
Code
table(data_2025_complete$N28, useNA = "ifany")

   1    2 
 562 1701 
Code
# Show who answered when they shouldn't have
table(data_2025_complete$N29_1[data_2025_complete$N28 != 1], useNA = "ifany")

<NA> 
1701 
Code
table(data_2025_complete$N30[data_2025_complete$N28 != 1], useNA = "ifany")

<NA> 
1701 
Code
table(data_2025_complete$N31[data_2025_complete$N28 != 1], useNA = "ifany")

<NA> 
1701 
Code
table(data_2025_complete$N32_1[data_2025_complete$N28 != 1], useNA = "ifany")

<NA> 
1701 
Code
table(data_2025_complete$N32_2_none[data_2025_complete$N28 != 1], useNA = "ifany")

<NA> 
1701 
Code
print("Check C: DCE-PART")
[1] "Check C: DCE-PART"
Code
print("Q26 Routing Logic")
[1] "Q26 Routing Logic"
Code
# Q26=1 -> trigger Q26a
# Q26=2 -> trigger Q26b
# Q26=3 -> trigger Q26c

# Count inconsistencies
data_2025_complete %>%
  filter((Q26 == 1 & is.na(Q26a)) |
         (Q26 == 2 & is.na(Q26b)) |
         (Q26 == 3 & is.na(Q26c))) %>%
  nrow()
[1] 0
Code
count(data_2025_complete, Q26, Q26a, Q26b, Q26c) 
Simple feature collection with 11 features and 5 fields
Geometry type: MULTIPOINT
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 11 × 6
     Q26  Q26a  Q26b  Q26c     n                                        geometry
 * <dbl> <dbl> <dbl> <dbl> <int>                                <MULTIPOINT [°]>
 1     1     1    NA    NA   184 ((24.28938 54.04921), (14.26094 52.15201), (14…
 2     1     2    NA    NA    88 ((6.328122 33.43144), (6.328119 33.43144), (6.…
 3     1     3    NA    NA    86 ((14.49389 52.27651), (14.60507 51.96806), (13…
 4     2    NA     1    NA   126 ((33.1082 40.97438), (14.69295 51.09008), (13.…
 5     2    NA     2    NA    70 ((32.91229 46.0284), (14.29066 51.66917), (14.…
 6     2    NA     3    NA   188 ((9.519691 55.50398), (13.66483 51.03029), (12…
 7     3    NA    NA     1   118 ((14.63419 51.68781), (13.1917 48.97575), (8.2…
 8     3    NA    NA     2   187 ((-1.858765 43.34529), (14.04597 51.92539), (1…
 9     3    NA    NA     3   417 ((8.255586 55.65127), (14.65548 51.93426), (13…
10     3    NA    NA     4   204 ((14.39528 52.39488), (14.42663 51.57859), (14…
11     3    NA    NA     5   595 ((-4.148713 33.64863), (8.173572 55.85895), (2…
Code
print("Check Conditional Routing for Q29 and Q29a")
[1] "Check Conditional Routing for Q29 and Q29a"
Code
# If Q28 ∈ [1,2], the respondent should answer Q29
# If Q28 == 3, they should answer Q29a
# Check routing consistency
data_2025_complete %>%
  filter((Q28 %in% c(1,2) & is.na(Q29)) |
         (Q28 == 3 & is.na(Q29a))) %>%
  nrow()
[1] 0
Code
# test for false positives
data_2025_complete %>%
  filter((Q28 %in% c(1,2) & !is.na(Q29a)) |
         (Q28 == 3 & !is.na(Q29))) %>%
  nrow()
[1] 0
Code
count(data_2025_complete, Q28, Q29, Q29a) 
Simple feature collection with 9 features and 4 fields
Geometry type: MULTIPOINT
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 9 × 5
    Q28   Q29  Q29a     n                                               geometry
* <dbl> <dbl> <dbl> <int>                                       <MULTIPOINT [°]>
1     1     1    NA    86 ((13.1451 50.48988), (8.2794 47.64178), (7.78862 49.2…
2     1     2    NA    81 ((-4.148713 33.64863), (14.39528 52.39488), (13.77217…
3     1     3    NA    36 ((13.10249 49.07096), (12.82742 49.0071), (8.573161 4…
4     2     1    NA   162 ((33.1082 40.97438), (13.08513 48.87533), (12.39174 4…
5     2     2    NA   430 ((-1.858765 43.34529), (6.328122 33.43144), (6.328119…
6     2     3    NA   541 ((8.173572 55.85895), (15.53532 52.50372), (14.45093 …
7     3    NA     1   113 ((24.63728 59.43429), (24.28938 54.04921), (14.26094 …
8     3    NA     2   165 ((32.91229 46.0284), (14.59118 51.75257), (14.85455 5…
9     3    NA     3   649 ((6.328102 33.43144), (9.519691 55.50398), (24.42833 …
Code
print("Check if Summary Description and Q31 Were Displayed Correctly")
[1] "Check if Summary Description and Q31 Were Displayed Correctly"
Code
# Everyone who saw the summary image (status quo mock-up) should have answered Q31
# If Q31 < 5 --> Q31a should be answered

data_2025_complete %>%
  filter(is.na(Q31_1)) %>%
  nrow()
[1] 0
Code
data_2025_complete %>%
  filter(Q31_1 < 5 & is.na(Q31a_1)) %>%
  nrow()
[1] 0
Code
count(data_2025_complete, Q31_1, Q31a_1)
Simple feature collection with 84 features and 3 fields
Geometry type: GEOMETRY
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 84 × 4
   Q31_1 Q31a_1                                      n                  geometry
 * <dbl> <chr>                                   <int>            <GEOMETRY [°]>
 1     1 ""                                          3 MULTIPOINT ((10.58988 51…
 2     1 "abgestorbene bäume"                        1 POINT (14.21837 52.16511)
 3     1 "es sind mehr Baumarten"                    1 POINT (8.576292 48.76298)
 4     1 "vom Borkenkäfer aufgefressen"              1 POINT (10.61691 51.72486)
 5     2 ""                                          1 POINT (8.383942 50.78814)
 6     2 "Bäume waren abgestorben"                   1 POINT (11.13062 51.48121)
 7     2 "Es war kurz nach dem Sturm und Hagel …     1 POINT (8.934975 48.61725)
 8     2 "da gibt es ZU viele verschiedene Arte…     1 POINT (8.418358 48.98416)
 9     2 "viele vetrocknete bäume"                   1 POINT (14.21974 52.16634)
10     2 "zu viele nadelbäume"                       1 POINT (9.127526 48.76064)
# ℹ 74 more rows
Code
print("Check for Internal Consistency") # can be extended
[1] "Check for Internal Consistency"
Code
# E.g. for a claimed high forest height (Q28 = 3) but low naturalness in Q30 might be interesting
test <- data_2025_complete %>%
  filter(Q28 == 3 & Q30 %in% c(1, 2)) # 42 obs

rm(test)

print("Other considered attributes: Q36 show if Q35_1a==2")
[1] "Other considered attributes: Q36 show if Q35_1a==2"
Code
attr(data_2025_complete$Q35_1a, "label") 
[1] "Q35. Were there any characteristics that you did not take into account when making your choices? (Yes, I did not consider)"
Code
table(data_2025_complete$Q35_1a, useNA = "ifany") # does not indicate anything

   0 
2263 
Code
attr(data_2025_complete$Q35_97, "label")
[1] "Q35. Were there any characteristics that you did not take into account when making your choices? (No, I considered all forest characteristics)"
Code
table(data_2025_complete$Q35_97, useNA = "ifany") # 62 respondents overlooked none of the attributes

   0    1 
1421  842 
Code
#View(data_2025_complete[, c("Q35_1a", "Q35_1", "Q35_2", "Q35_3", "Q35_4", "Q35_5", "Q35_6", "Q35_7", "Q35_97")])

data_2025_complete %>%
  filter(Q35_1 == 1 |
         Q35_2 == 1 |
         Q35_3 == 1 |
         Q35_4 == 1 |
         Q35_5 == 1 |
         Q35_6 == 1 |
         Q35_7 == 1) %>%
  nrow() # 99
[1] 1421
Code
table(data_2025_complete$Q35_1a, data_2025_complete$Q35_97, useNA = "ifany")
   
       0    1
  0 1421  842
Code
count(data_2025_complete, Q35_97, Q36_1, Q36_2, Q36_3, Q36_4, Q36_5, Q36_6, Q36_7)
Simple feature collection with 417 features and 9 fields
Geometry type: GEOMETRY
Dimension:     XY
Bounding box:  xmin: -115.2727 ymin: 33.43144 xmax: 33.1082 ymax: 64.10578
Geodetic CRS:  WGS 84
# A tibble: 417 × 10
   Q35_97 Q36_1                        Q36_2 Q36_3 Q36_4 Q36_5 Q36_6 Q36_7     n
 *  <dbl> <chr>                        <chr> <chr> <chr> <chr> <chr> <chr> <int>
 1      0 I did not notice it in the … I di… I di… I di… I di… I di… I di…     1
 2      0 I did not notice it in the … I di… I di… I di… <NA>  I di… I di…     2
 3      0 I did not notice it in the … I di… I di… I di… <NA>  <NA>  <NA>      1
 4      0 I did not notice it in the … I di… I di… <NA>  I di… <NA>  <NA>      1
 5      0 I did not notice it in the … I di… I di… <NA>  <NA>  I di… I di…     1
 6      0 I did not notice it in the … I di… I di… <NA>  <NA>  I di… <NA>      1
 7      0 I did not notice it in the … I di… I di… <NA>  <NA>  <NA>  <NA>      4
 8      0 I did not notice it in the … I di… I fo… I fo… It i… <NA>  <NA>      1
 9      0 I did not notice it in the … I di… I fo… <NA>  <NA>  It i… I fo…     1
10      0 I did not notice it in the … I di… I fo… <NA>  <NA>  <NA>  <NA>      1
# ℹ 407 more rows
# ℹ 1 more variable: geometry <GEOMETRY [°]>
Code
print("Forest visit: Q38 and Q39 Routing Logic")
[1] "Forest visit: Q38 and Q39 Routing Logic"
Code
# If Q38 = 1 (yes, visited other forests) --> Show Q39
# If Q38 = 2, skip Q39 and all follow-up questions

attr(data_2025_complete$Q38, "labels") 
NULL
Code
table(data_2025_complete$Q38)

   1    2 
1120 1143 
Code
#Q39: If Q38 == 1 (visited other forests)
#Q40a–Q42a: If Q39 == 2 (visited 2nd forest)
#Q41b–Q43b: If Q39 %in% 3:6 (visited 3–5 forests)
#Q41c–Q43c: If Q39 %in% 4:6 (visited 4–6 forests)

# 1. Q39 should be NA if Q38 == 2 (didn't visit other forests)
data_2025_complete %>% filter(Q38 == 2 & !is.na(Q39)) %>% nrow()
[1] 0
Code
data_2025_complete %>% filter(Q38 == 2 & is.na(Q39)) %>% nrow()
[1] 1143
Code
# 2. Q40a–Q42a only if Q39 == 2
data_2025_complete %>% filter(Q39 != 2 & (!is.na(Q40a_1) | !is.na(Q40a_2) | !is.na(Q41a_1) | !is.na(Q41a_2) | !is.na(Q41a_9_none) | !is.na(Q41ax) | !is.na(Q42a_1))) %>% nrow()
[1] 312
Code
# 3. Q41b–Q43b only if Q39 in 3:6
data_2025_complete %>% filter(!(Q39 %in% 3:6) & (!is.na(Q41b_1) | !is.na(Q41b_2) | !is.na(Q42b_1) | !is.na(Q42b_2) | !is.na(Q42b_9_none) | !is.na(Q42bx) | !is.na(Q43b_1) | !is.na(Q41c_1) | !is.na(Q41c_2) | !is.na(Q42c_1) | !is.na(Q42c_2) | !is.na(Q42c_9_none) | !is.na(Q42cx) | !is.na(Q43c_1))) %>% nrow()
[1] 754
Code
# 4. Optional: Check if expected data is missing when it should be present

# 4.1 Q39 == 2 --> Check for missing responses in forest 
data_2025_complete %>%
  filter(Q39 == 2 & (
    is.na(Q40a_1) |
    is.na(Q40a_2) |
    is.na(Q41a_1) |
    is.na(Q41a_2) |
    is.na(Q41a_9_none) |
    is.na(Q41ax) |
    is.na(Q42a_1)
  )) %>%
  summarise(
    across(
      c(Q40a_1, Q40a_2, Q41a_1, Q41a_2, Q41a_9_none, Q41ax, Q42a_1),
      ~ sum(is.na(.))
    )
  )
Simple feature collection with 1 feature and 7 fields (with 1 geometry empty)
Geometry type: GEOMETRYCOLLECTION
Dimension:     XY
Bounding box:  xmin: NA ymin: NA xmax: NA ymax: NA
Geodetic CRS:  WGS 84
# A tibble: 1 × 8
  Q40a_1 Q40a_2 Q41a_1 Q41a_2 Q41a_9_none Q41ax Q42a_1                 geometry
   <int>  <int>  <int>  <int>       <int> <int>  <int> <GEOMETRYCOLLECTION [°]>
1      0      0      0      0           0     0      0 GEOMETRYCOLLECTION EMPTY
Code
# 4.2 Q39 ∈ 3:6 --> Check for missing responses in forest 
data_2025_complete %>%
  filter(Q39 %in% 3:6 & (
    is.na(Q41b_1) &
    is.na(Q41b_2) &
    is.na(Q42b_1) &
    is.na(Q42b_2) &
    is.na(Q42b_9_none) &
    is.na(Q42bx) &
    is.na(Q43b_1) &
    is.na(Q41c_1) &
    is.na(Q41c_2) &
    is.na(Q42c_1) &
    is.na(Q42c_2) &
    is.na(Q42c_9_none) &
    is.na(Q42cx) &
    is.na(Q43c_1)
  )) %>%
  nrow() # no missing values
[1] 0
Code
print("Berries & Mushrooms")
[1] "Berries & Mushrooms"
Code
# Q46   Should be answered (non-NA) only if Q45 == 1 (i.e., mushrooms were collected)
# Q48   Should be answered (non-NA) only if Q47 == 1 (i.e., berries were collected)

table(data_2025_complete$Q45)

   1    2 
 568 1695 
Code
data_2025_complete %>%
  filter(Q45 != 1 & Q46_1 != "" & !is.na(Q46_1)) %>%
  nrow()
[1] 0
Code
#View(data_2025_complete[,c("Q45", "Q46_1")])

table(data_2025_complete$Q47)

   1    2 
 520 1743 
Code
# Should NOT be answered if Q47 != 1
data_2025_complete %>%
  filter(Q47 != 1 & Q48_1 != "" & !is.na(Q48_1)) %>%
  nrow()
[1] 0
Code
# Should be answered if Q47 == 1
data_2025_complete %>%
  filter(Q47 == 1 & Q48_1 == "") %>%
  nrow()
[1] 0
Code
#View(data_2025_complete[,c("Q47", "Q48_1")])
Code
print("Check D: DEMOGRAPHY")
[1] "Check D: DEMOGRAPHY"
Code
print("M11: M10 >= 2017")
[1] "M11: M10 >= 2017"
Code
data_2025_complete %>%
  filter((M10_1 < 2017) & !is.na(M11)) %>%
  nrow()
[1] 0
Code
#View(data_2025_complete[,c("M10_1","M10_2_none","M11")])
Code
print("Check E: Ownership")
[1] "Check E: Ownership"
Code
print("Trigger several questions if EIG1==1")
[1] "Trigger several questions if EIG1==1"
Code
data_2025_complete %>%
  filter((EIG1 !=1) & (!is.na(EIG2_1) & !is.na(EIG2_2_none))) %>%
  nrow()
[1] 0
Code
data_2025_complete %>%
  filter((EIG1 ==1) & (is.na(EIG2_1) & is.na(EIG2_2_none))) %>%
  nrow()
[1] 0
Code
data_2025_complete %>%
  filter((EIG1 !=1) & (!is.na(EIG3_1) & !is.na(EIG3_2_none))) %>%
  nrow()
[1] 0
Code
#View(data_2025_complete[,c("EIG1","EIG2_2_none","EIG2_1","EIG3_2_none","EIG3_1")])
Code
print("Check F: Drought") # 80 respondents in this survey split (81 on other survey split)
[1] "Check F: Drought"
Code
print("Trigger several questions only if A2 AND A3 != “No, not at all”")
[1] "Trigger several questions only if A2 AND A3 != “No, not at all”"
Code
table(data_2025_complete$A2, useNA = "ifany")

  1   2   3   4   5 
387 964 436 378  98 
Code
table(data_2025_complete$A3, useNA = "ifany")

  1   2   3   4   5 
358 997 456 362  90 
Code
table(data_2025_complete$A2, data_2025_complete$A3, useNA = "ifany")
   
      1   2   3   4   5
  1 255 122   7   1   2
  2  79 704 128  53   0
  3  14 112 246  60   4
  4   9  56  61 232  20
  5   1   3  14  16  64
Code
# data_2025_complete %>% filter(A2 == 5 & A3 == 5) %>% 
#   select(A2, A3, A5, A6, A8) %>%
#   View()
#%>% nrow() # 8 times the case that questions are not triggered

sum(!(data_2025_complete$A2 == 5 & data_2025_complete$A3 == 5), na.rm = TRUE) # --> but 8 is counting both survey versions. QUestion: how many got not triggered only in survey version for drought?
[1] 2199
Code
data_2025_complete %>%
  filter((A2 ==5 & A3==5) & (!is.na(A5) & !is.na(A6) & !is.na(A8))) %>%
  nrow()
[1] 0
Code
data_2025_complete %>%
  filter((A2 !=5 | A5!=5) & (!is.na(A5) | !is.na(A6) | !is.na(A8))) %>%
  nrow()   # 74 responses, so for 6 respondents questions not triggered
[1] 1073
Code
table(data_2025_complete$A5, useNA = "ifany") # answered by 74, NA:87  

   1    2    3    4    5    6 <NA> 
  27  249  505   76   60  157 1189 
Code
table(data_2025_complete$A6, useNA = "ifany") # answered by 74, NA:87

   1    2    3    4    5    6 <NA> 
   9   71  672  102   33  187 1189 
Code
table(data_2025_complete$A8, useNA = "ifany") # answered by 68, NA: 93 --> lower respondents rate and higher NA than there should be (mandatory question and no further drop-outs), also the question did not appear in test version of the survey when I tried again (same for A9 but this is conditional on A9 therefore not surprising), check again

   1    2 <NA> 
 193  881 1189 
Code
table(data_2025_complete$A9_1, useNA = "ifany") 

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       2142 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          - 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                 Ich suche Abwechslung und neue Impressionen. Andere Gebiete bieten verschiedene Landschaften und Pflanzen. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ruhigere oder weniger frequentierte Orte sucht 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                  Vielfalt der Natur  Erklärung: Ich suche nach neuen Erlebnissen und möchte verschiedene Landschaften und Ökosysteme entdecken. Andere Gebiete bieten möglicherweise einzigartige Flora und Fauna, die ich erleben möchte. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                         "Ich habe meine Waldbesuche auf andere Gebiete verlegt, weil die Wälder in meiner Region stärker von Dürreschäden betroffen sind." 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        alles okay und gut! 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            andre eindrücke 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                asd a sda d 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 auch mal andere zu sehen.- 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                        Aufgrund der besseren Infrastruktur und der vielfältigeren Wandermöglichkeiten in anderen Gebieten. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                   Aufgrund von Bauarbeiten im ursprünglichen Gebiet habe ich meine Waldbesuche umgeleitet. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Baum, okay. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Because the air quality is better in other places. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          2 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Consider the air quality and environment of the forest. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                               Damit ich auch andere Gebieten besuchen kann, auch um neue Pilz und Beeren Flecken zu finden. Auch wenn Dürreschäden sind, so gehe ich in denselben Wald, weil ich ihn von klein auf kannte. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Das weiß ich nicht 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Das wird es nicht. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                           Der frühere Wald war zu stark frequentiert, also suchte ich einen ruhigeren Ort für Entspannung. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                     Die Änderungen der Häufigkeit, mit der ich die Wälder in Deutschland besuche, hängen hauptsächlich von der Jahreszeit und der Arbeitsrhythmus ab. Im Frühling und Sommer wirkt der Wald wie verzaubert 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      die natürliche Umwelt 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Die Umgebung ist nicht mehr geeignet. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Die ursprüngliche regionale Ökologie wird überlastet oder geschädigt 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           Die Wälder in anderen Gebieten sehen besser aus. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Discovered other places with a better environment. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          2 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       dort sind mehr Tiere 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               Eine andere Landschaft sehen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Eine bessere Umgebung anstreben 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 Einfach so 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Enim non sed aliquip quod quod vitae ea minim magna 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             es gibt noch viel zu entdecken 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               es ist immer wichtig und sio 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                            Es war ein Besuch von Verwandtschaft und ein Spaziergang in der näheren Umgebung dieser Familie 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Facere ut perferendis voluptate aperiam 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             für balanziert 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               Gegend hat mich interessiert 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       good 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          2 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               hab ich so nicht nachgedacht 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           hatte lust drauf 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   i couldn‘t cover the distance like befor 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 I don't want to worsen the condition of the forest by further intervention 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ich ahbe kein ehanung 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                            Ich besuche die Wälder, wo ich in der Nähe bin (Urlaub oder andere Aktivitäten) 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Ich besuche jetzt lieber Wälder in der nähe von Flüssen und Bächen. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Ich bleibe lieber in der Nähe 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ich denke das es am entspannendesten sit 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                          Ich habe meine Waldbesuche auf andere Gebiete verlegt, weil die ursprünglichen Gebiete zu überfüllt waren und ich eine ruhigere und entspanntere Erfahrung suche. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                          Ich habe meine Waldbesuche auf andere Gebiete verlegt, weil diese ruhiger, naturnäher oder abwechslungsreicher sind als mein bisheriger Wald.    Weitere mögliche Gründe könnten sein:    Bessere Wege oder Infrastruktur (z.???B. Parkplätze, Sitzbänke, ausgeschilderte Routen)    Schönere Landschaft oder mehr Vielfalt in Flora und Fauna    Weniger Menschen – für mehr Erholung und Stille 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                 Ich habe meine Waldbesuche verlegt, um bessere Zugänglichkeit, schönere Landschaften und weniger Touristen zu finden – alles, was das Erlebnis verbessert. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Ich halte ausschau nach interessanteren wäldern 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Ich möchte einen neuen Ort besuchen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Ich suche immer mal wieder Abwechslung 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ich wechsel häufig die Waldgebiete um neues kennenzulernen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Ich wollte neue natürliche Umgebungen erkunden. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
If it refers to the metaphorical expression "forest journey", I can understand it as referring to a certain plan, goal, or change in one's life path. The reason for changing the "forest journey" might be to seek new experiences and challenges, or because the original path has encountered unforeseen obstacles or a situation where it cannot continue to progress. Just like traveling in a forest, sometimes you may find that the path no longer suits you, or you may desire to explore different landscapes and unknown places. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                In der Regel wegen der Luftqualitätsprobleme und der Umwelt 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  interesse 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   intuitiv 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ist näher an meinem Wohort 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         JA 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            just to explore 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      keine 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               keine ahnung 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             Köttinger wALD 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Lieber den weinberg. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          3 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             mal was anders 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              mal was neues 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                Man wechselt die Waldreise, um verschiedene Waldtypen kennenzulernen – von dunkeln Nadelwäldern bis zu sonnigen Laubwäldern. Jeder hat seine eigene Flora, Fauna und Atmosphäre, und so entdeckt man die Vielfalt der Natur auf neue Weise. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 mehr sehen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   Mir gefällt die umgebung 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  möchte auch mal woanders gehen und neu Pilzgebiete finden 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Nähe 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               Neue Wälder kennenzulernen und suche nach neuen Alternativen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         neue Wege erkunden 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       none 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    play in fragmented time 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Ruhigere oder weniger überfüllte Orte 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Schauen Sie sich verschiedene Bäume an 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Schöner anzusehen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   schonung 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            schwer zu sagen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   sehr gut 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          2 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               sind schöner 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      sind und ich habe gerade gesehen habe 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  um etwas neues zu endeken 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          2 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             Um neue Gebiete kennenzulernen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   um Neues kennen zulernen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          um was anderes zu sehen als sonst 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      um was neues zu sehen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Umwelt schlechter, neuer Ort. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             umwelt zuliebe 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      umzug 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Vielseitigkeit, um andere kennenzulernen. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                          Waldbesuche werden aufgrund einer Reihe von Faktoren häufig in andere Gebiete verlagert, darunter Änderungen der Waldzugänglichkeit, der Umweltbedingungen, Naturschutzbemühungen und persönliche Vorlieben für neue Erfahrungen. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                      war zu überfüllt mit BesucherInnen, sodass ich keine Ruhe im Wald genießen konnte. Deshalb wechselte ich den Ort, um die Natur in Frieden zu erleben. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       was neues zur sehen. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                Weil das ehemalige Waldgebiet durch übermäige Tourismus - Entwicklung beeinträchtigt wurde. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Weil die Hitze das nicht erlaubte 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Weil die neuen Gebiete näher an meinem Zuhause sind. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Weil die Wälder dort in einem besseren Zustand sind 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Weil es besser ist 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          2 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   weil es schöner dort ist 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               weil es schöner gebiete gibt 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                weil ich abwechslung wollte 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      weil ich den Wald nicht noch weiter zerstören wollte. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           Weil ich gerne Abwechslung hätte 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         weil ich mochte andere walde sehen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                      Weil ich zu einem anderen Wald wechselte, um die natürliche Ökologie des aktuellen Waldgebiets zu schützen, sodass die natürliche Ökosystem-Umgebung erhalten bleibt. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                   Weil jeder Wald einzigartig ist: andere Bäume, Tiere, Landschaften. Neue Pfade bringen Frische, Entdeckungen und eine andere Verbindung zur Natur – ein Wechsel stärkt die Lebensfreude. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        weil sie schön sind 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 weil sie zu weit weg waren 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            werden kann ich 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Wollte was Neues sehen 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Zu voll, Ruhe gesucht. 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1 
Code
# View(data_2025_complete[,c("A2","A3","A5","A6","A8")])

print("Trigger A7 only if A6==1|2|4|5")
[1] "Trigger A7 only if A6==1|2|4|5"
Code
data_2025_complete %>%
  filter((A6 == 3 | A6 == 6) & A7_1 != "") %>%
  nrow()
[1] 0
Code
print("Trigger A9 only if A8==1")
[1] "Trigger A9 only if A8==1"
Code
data_2025_complete %>%
  filter(A8 == 2 & A9_1 != "") %>%
  nrow()
[1] 0

Spatial Distribution of Forest Visits

Code
pal <- colorNumeric(
  palette = "viridis", 
  domain = log1p(data_2025_complete$num_visits)
)

leaflet(data_2025_complete) %>%
  addProviderTiles("OpenStreetMap") %>%
  addCircleMarkers(
   
    fillColor = ~pal(log1p(num_visits)),  # log1p here
    fillOpacity = 0.7,
    color = "#444444",
    weight = 0.5,
    popup = ~paste("Forest Visits:", num_visits)
  ) %>%
  addLegend(
    "bottomright",
    pal = pal,
    values = ~log1p(num_visits),  # log1p here
    title = "Forest Visits (log scale)",
    opacity = 0.7,
    labFormat = labelFormat(transform = function(x) round(expm1(x)))  # back-transform legend labels
  )
Code
# print("Check distance to nearby village location")
# summary(data_2025_complete_check$dist_check/1000)
# 
# print("Nearby village more than 20km away?")
# table(data_2025_complete_check$dist_check >= 20000)
# 
# print("Nearby village more than 100km away?")
# table(data_2025_complete_check$dist_check >= 100000)
# 
# ggplot(data = data_2025_complete_check) +
#   geom_boxplot(aes(x = factor(M2a), y = dist_check / 1000), na.rm = TRUE) +
#   labs(x = "M2a", y = "Distance (km)")

Locations of the respondents

Code
data_2025_complete_filt <- data_2025_complete %>%
  mutate(
    lat = N8_1,
    lon = N8_2,
    # reason for invalidity (first match wins)
    invalid_reason = case_when(
      is.na(lat) & is.na(lon)                      ~ NA_character_,           # both missing = not "invalid", just missing
      xor(is.na(lat), is.na(lon))                  ~ "only_one_missing",
      !is.finite(lat) | !is.finite(lon)            ~ "non_finite",
      lat == 0 & lon == 0                          ~ "null_island_0_0",
      lat < -90 | lat > 90                         ~ "lat_out_of_range",
      lon < -180 | lon > 180                       ~ "lon_out_of_range",
      TRUE                                         ~ ""
    ),
    valid_combo = invalid_reason == ""
  ) %>% filter(valid_combo == "TRUE")

data_2025_complete_filt$geometry3 <- st_sfc(
  Map(function(lon, lat) st_point(c(lon, lat)), 
      data_2025_complete_filt$N8_2,  # longitude
      data_2025_complete_filt$N8_1), # latitude
  crs = 4326
)



leaflet(data_2025_complete_filt) %>%
  addTiles() %>%  # Adds OpenStreetMap base layer
  addMarkers(data = st_set_geometry(data_2025_complete_filt, "geometry3"))
Code
data_2025_complete <- data_2025_complete %>%
  mutate(
    geometry_proj1 = st_transform(geometry, 3857),  
    geometry_proj4 = st_transform(geometry_depart, 3857)
  )


data_2025_complete$dist_por_for <- st_distance(
  data_2025_complete$geometry_proj1,
  data_2025_complete$geometry_proj4,
  by_element = TRUE
)

print("Distance departure point to forest")
[1] "Distance departure point to forest"
Code
summary(data_2025_complete$dist_por_for/1000)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
    0.053     3.314    13.666    97.268    69.507 14067.930 

Socio-demographic Overview

Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x = M2a, fill = M2a), position = "dodge") +
  labs(title = "Federal States", x = "", y = "Count") +
  theme_minimal() +
  scale_fill_brewer(palette = "Set3")

Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x = M3_1, fill = M3_1), position = "dodge") +
  labs(title = "Age Distribution", x = "", y = "Count") +
  theme_minimal() +
  scale_fill_brewer(palette = "Set3")

Code
table(data_2025_complete$M3v)

  1   2   3   4   5   6 
 82 456 627 358 338 402 
Code
print("Gender")
[1] "Gender"
Code
table(data_2025_complete$M1)

   1    2    3 
1181 1078    4 
Code
attr(data_2025_complete$M2, "labels")
NULL
Code
ggplot(data = data_2025_complete) +
  geom_bar(aes(x = M2), position = "dodge") +
  labs(title="Settlement type")

Code
attr(data_2025_complete$M4, "labels")
NULL
Code
ggplot(data = data_2025_complete) +
  geom_bar(aes(x = M4), position = "dodge") +
  labs(title="Education")

Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x = as.factor(M4a)), position = "dodge") +
  labs(title = "Life Satistfaction", x = "", y = "Count") +
  theme_minimal() +
  scale_fill_brewer(palette = "Set3")

Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x = as.factor(M9)), position = "dodge") +
  labs(title = "Net Income", x = "", y = "Count") +
  theme_minimal() +
  scale_fill_brewer(palette = "Set3")

Code
ggplot(data=subset(data_2025_complete, M5_1 < 20)) +
  geom_boxplot(aes(x="", y=M5_1)) +
  labs(title="HH Size")

Code
ggplot(data=subset(data_2025_complete, M5_1 < 20)) +
    geom_bar(aes(x=M5_1)) +
    labs(title="HH Size")

Code
ggplot(data=data_2025_complete) +
    geom_bar(aes(x=M7_1)) +
    labs(title="Kids in HH")

Code
ggplot(data=data_2025_complete) +
    geom_bar(aes(x=M10_1)) +
    labs(title="Living in Region since")

Flag weird entries

Code
table(data_2025_complete$red_flag_2000)

   0    1 
2197   66 
Code
table(data_2025_complete$red_flag)

   0    1 
2251   12 
Code
table(data_2025_complete$speeder_flag)

   0 
2263 
Code
table(data_2025_complete$flag_out_germany)

   0    1 
2244   19 

Compare 2017 and 2025

Code
combined <- rbind(
  data.frame(age = 2017 - data_2017_complete$M3, year = 2017),
  data.frame(age = 2025 - data_2025_complete$M3_1, year = 2025)
)

# --- Option A: BINS (recommended for comparison) ---
combined <- combined %>%
  mutate(age_group = cut(
    age,
    breaks = c(-Inf, 29, 39, 49, 60, Inf),
    labels = c("18–29", "30–39", "40–49", "50–60", "60+"),
    right = TRUE
  ))

# Count per (year, age_group) and convert to proportion within each year
bin_props <- combined %>%
  filter(!is.na(age_group)) %>%
  count(year, age_group, name = "n") %>%
  group_by(year) %>%
  mutate(prop = n / sum(n)) %>%
  ungroup()

ggplot(bin_props, aes(x = age_group, y = prop, fill = factor(year))) +
  geom_col(position = "dodge") +
  labs(title = "Age Distribution Comparison",
       x = "Age Group", y = "Proportion", fill = "Sample") +
  theme_minimal() +
  scale_fill_manual(values = c("2017" = "orange", "2025" = "forestgreen"))

Code
#### Compare distance

df <- bind_rows(
  data.frame(year = "2017", dist = factor(database_2017$dist_3)),
  data.frame(year = "2025", dist = factor(database_2025$dist_3))
)

# Ensure consistent ordering of categories
df$dist <- factor(df$dist, levels = sort(unique(df$dist)))

freq <- df %>%
  count(year, dist) %>%
  group_by(year) %>%
  mutate(pct = n / sum(n))

ggplot(freq, aes(x = dist, y = pct, fill = year)) +
  geom_col(position = "dodge") +
  scale_y_continuous(labels = scales::percent) +
  labs(x = "Distance category (in km)", y = "Relative share",
       title = "Comparison of forest travel distances") +
  scale_fill_manual(values = c("2017" = "orange", "2025" = "forestgreen")) +
  theme_minimal()

Code
#### Federal state distribution of respondents 2017 vs 2025 ####

count_share <- function(df, year_label) {
  df %>%
    sf::st_drop_geometry() %>%    
    filter(!is.na(NAME_2)) %>%
    filter(!is.na(NAME_1)) %>%
    count(NAME_1, name = "n") %>%
    mutate(year = year_label) %>%
    group_by(year) %>%
    mutate(share = n / sum(n)) %>%
    ungroup()
}

dist17 <- count_share(data_2017_complete, "2017")
dist25 <- count_share(data_2025_complete, "2025")

# Combine; ensure all counties exist for both years (fill with zeros)
all_counties <- union(dist17$NAME_1, dist25$NAME_1)
dist <- bind_rows(dist17, dist25) %>%
  complete(NAME_1 = all_counties, year = c("2017","2025"),
           fill = list(n = 0, share = 0)) %>%
  mutate(NAME_2 = fct_reorder(NAME_1, share, .fun = sum, .desc = TRUE))

n2017 <- sum(dist17$n); n2025 <- sum(dist25$n)

ggplot(dist, aes(x = NAME_1, y = share, fill = year)) +
  geom_col(position = position_dodge(width = 0.8), width = 0.7, alpha = 0.85) +
  scale_y_continuous(labels = percent_format(accuracy = 1)) +
  scale_fill_manual(values = c("2017" = "orange", "2025" = "forestgreen")) +
  labs(title = "Federal state distribution of respondents (relative shares)",
       x = "", y = "Share of sample", fill = "Year") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "top", panel.grid.major.y = element_blank()) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) 

Forest Visit Stats

Code
attr(data_2025_complete$M2a, "labels")
NULL
Code
ggplot(data = data_2025_complete) +
  geom_boxplot(aes(x = factor(M2a), y = N7, fill = factor(M2a)), 
               position = "dodge", outlier.shape = NA) +
  labs(title = "Forest Visits", x = "M2a", y = "N7_1") +
  theme_minimal() + 
  scale_y_continuous(limits = c(0, 80)) 

Spatial Forest Characteristics

Code
pal <- colorFactor(
  palette = c("green", "yellow", "red"),
  domain = c(1, 2, 3)
)

leaflet(data_2025_complete) %>%
  addProviderTiles("OpenStreetMap") %>%
  addCircleMarkers(
    radius = 5,
    fillColor = ~pal(Q30),
    fillOpacity = 0.7,
    color = "#444444",
    weight = 0.5,
    popup = ~paste("Deadwood Indicator:", Q30)
  ) %>%
  addLegend(
    "bottomright",
    pal = pal,
    values = ~Q30,
    title = "Deadwood Indicator",
    opacity = 0.7,
    labFormat = labelFormat(
      transform = identity,
      digits = 0
    )
  )
Code
forest_labels <- c("1" = "Coniferous", "2" = "Broadleaved", "3" = "Mixed")
pal_q26 <- colorFactor(
  palette = c("darkgreen", "saddlebrown", "orange"),
  domain = c(1, 2, 3)
)

leaflet(data_2025_complete) %>%
  addProviderTiles("OpenStreetMap") %>%
  addCircleMarkers(
    radius = 5,
    fillColor = ~pal_q26(Q26),
    fillOpacity = 0.7,
    color = "#444444",
    weight = 0.5,
    popup = ~paste("Forest Type:", forest_labels[as.character(Q26)])
  ) %>%
  addLegend(
    "bottomright",
    pal = pal_q26,
    values = ~Q26,
    title = "Forest Type",
    opacity = 0.7,
    labels = c("1" = "Coniferous", "2" = "Broadleaved", "3" = "Mixed")
  )
Code
attr(data_2025_complete$N5, "labels")
NULL
Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x = N5), position = "dodge") +
  labs(title = "Time Spend in Forest", x = "", y = "Count") +
  theme_minimal() 

Code
attr(data_2025_complete$N9, "labels")
NULL
Code
breaks_km <- c(-Inf, 1, 4, 9, 19, 39, 69, 99, 150, Inf)

labels_n9 <- c(
  "Less than 1 km", "1-4 km", "5-9 km", "10-19 km",
  "20-39 km", "40-69 km", "70-99 km", "100-150 km", "More than 150 km"
)


data_2025_complete$for_dis_labelled <- factor(data_2025_complete$for_dis, levels = 1:9, labels = labels_n9)

ggplot(data = data_2025_complete) +
  geom_bar(aes(x = for_dis_labelled), position = "dodge", fill = "steelblue") +
  labs(title = "Distance to Forest", x = "Distance Category", y = "Count") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Code
data_2025_complete$dist_bin <- cut(
  data_2025_complete$dist_por_for/ 1000,  # convert to km
  breaks = breaks_km,
  labels = labels_n9,
  right = TRUE,  # interval is (a, b]
  include.lowest = TRUE
)

true_counts <- data_2025_complete %>%
  mutate(bin = factor(for_dis, levels = 1:9, labels = labels_n9)) %>%
  count(bin, source = "Survey")

# For computed distances (assuming already labeled with same strings)
comp_counts <- data_2025_complete %>%
  filter(!is.na(dist_bin)) %>%
  mutate(bin = factor(dist_bin, levels = labels_n9)) %>%
  count(bin, source = "Computed")

# Combine and align factor levels
combined_counts <- bind_rows(true_counts, comp_counts) %>%
  mutate(bin = factor(bin, levels = labels_n9))

ggplot(combined_counts, aes(x = bin, y = n, fill = source)) +
  geom_bar(stat = "identity",
           position = "identity",
           alpha = 0.4,
           data = subset(combined_counts, source == "Survey")) +
  geom_bar(stat = "identity",
           position = "identity",
           alpha = 1, width = 0.5,
           data = subset(combined_counts, source == "Computed")) +
  scale_fill_manual(values = c("Survey" = "grey70", "Computed" = "indianred")) +
  theme_minimal() +
  labs(title = "Distance to Forest: Reported vs Computed",
       x = "Distance Category",
       y = "Count",
       fill = "") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Visualize trips

Code
df50 <- data_2025_complete %>% filter(flag_out_germany == 0) %>% slice(1:50)

# convenience handles
dep_pts <- df50$geometry_depart      # sfc(POINT)
for_pts <- df50$geometry_forest      # sfc(POINT)

# build a LINESTRING per row from (depart -> forest)
line_sfc <- st_sfc(
  mapply(function(p1, p2) {
    st_linestring(rbind(st_coordinates(p1), st_coordinates(p2)))
  }, dep_pts, for_pts, SIMPLIFY = FALSE),
  crs = st_crs(df50)
)

lines_sf <- st_sf(row = seq_len(nrow(df50)), geometry = line_sfc)

# wrap the two point columns into sf objects (so ggplot can layer them)
dep_sf <- st_sf(type = "depart", geometry = dep_pts)
for_sf <- st_sf(type = "forest", geometry = for_pts)

# plot
ggplot() +
  geom_sf(data=germany_fed, fill="white") + 
  geom_sf(data = lines_sf, linewidth = 0.7, alpha = 0.5) +
  geom_sf(data = dep_sf, size = 2, alpha = 0.9, col="blue") +
  geom_sf(data = for_sf, size = 2, alpha = 0.9, col="forestgreen") +
  # optional: color points differently
  labs(title = "First 50 rows: depart → forest",
       x = NULL, y = NULL) +
  theme_minimal()

Choice Experiment

Code
attr(data_2025_complete$Q26, "labels")
NULL
Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x=Q26), fill="forestgreen") +
  labs(title="Forest Type")

Code
attr(data_2025_complete$Q28, "labels")
NULL
Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x=Q28), fill="grey30") +
  labs(title="Tree Height")

Code
attr(data_2025_complete$Q29, "labels")
NULL
Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x=Q29), fill="darkorange") +
  labs(title="Age Composition")

Code
attr(data_2025_complete$Q30, "labels")
NULL
Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x=Q30), fill="cyan") +
  labs(title="Deadwood")

Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x=as.factor(Q31_1))) +
  labs(title="How well is forest displayed?")

Code
print("check randomization of blocks")
[1] "check randomization of blocks"
Code
table(data_2025_complete$CJ)

  1   2   3 
737 772 754 

Choices

Code
print("First choice")
[1] "First choice"
Code
table(data_2025_complete$CJ_1_1)

   1    2    3 
 555  468 1240 
Code
table(data_2025_complete$CJ_2_1)

   1    2    3 
 475  474 1314 
Code
table(data_2025_complete$CJ_3_1)

   1    2    3 
 338  427 1498 
Code
table(data_2025_complete$CJ_4_1)

   1    2    3 
 575  284 1404 
Code
table(data_2025_complete$CJ_5_1)

   1    2    3 
 311  623 1329 
Code
table(data_2025_complete$CJ_6_1)

   1    2    3 
 423  549 1291 
Code
table(data_2025_complete$CJ_7_1)

   1    2    3 
 462  388 1413 
Code
table(data_2025_complete$CJ_8_1)

   1    2    3 
 836  282 1145 
Code
table(data_2025_complete$CJ_9_1)

   1    2    3 
 505  424 1334 
Code
table(data_2025_complete$CJ_10_1)

   1    2    3 
 494  432 1337 
Code
table(data_2025_complete$CJ_11_1)

   1    2    3 
 365  601 1297 
Code
table(data_2025_complete$CJ_12_1)

   1    2    3 
 509  472 1282 
Code
print("Second choice")
[1] "Second choice"
Code
table(data_2025_complete$CJ_1_2)

  1   2   3 
867 757 639 
Code
table(data_2025_complete$CJ_2_2)

  1   2   3 
784 822 657 
Code
table(data_2025_complete$CJ_3_2)

  1   2   3 
797 982 484 
Code
table(data_2025_complete$CJ_4_2)

   1    2    3 
1008  689  566 
Code
table(data_2025_complete$CJ_5_2)

   1    2    3 
 562 1060  641 
Code
table(data_2025_complete$CJ_6_2)

  1   2   3 
685 878 700 
Code
table(data_2025_complete$CJ_7_2)

  1   2   3 
782 902 579 
Code
table(data_2025_complete$CJ_8_2)

  1   2   3 
854 662 747 
Code
table(data_2025_complete$CJ_9_2)

  1   2   3 
835 799 629 
Code
table(data_2025_complete$CJ_10_2)

  1   2   3 
845 816 602 
Code
table(data_2025_complete$CJ_11_2)

  1   2   3 
635 941 687 
Code
table(data_2025_complete$CJ_12_2)

  1   2   3 
724 842 697 

Check design with 2017 version

Code
print("Distance levels 2017")
[1] "Distance levels 2017"
Code
table(database_2017$dist_1)

 0.5    1    2    3    4    6    8    9   10   12   15   18   25   30   32   40 
1328  884  653 1122  638 1588  486  202  508 1555  204  512  731  213  469  364 
  45   50   60   65   90  125 
 126  222  102  192  192  237 
Code
print("Distance levels 2025")
[1] "Distance levels 2025"
Code
table(database_2025$alt1.dist_trans)

 0.5    1    2    3    4    6    8    9   10   12   15   18   25   30   32   40 
3434 1673 1003 2191 1023 3596  815  482  802 3413  546 1507 1768  508 1414  894 
  45   50   60   65   90  125 
 456  310  456  310  284  271 
Code
prop.table(table(database_2017$dist_1))

        0.5           1           2           3           4           6 
0.106002554 0.070561941 0.052123244 0.089559387 0.050925926 0.126756066 
          8           9          10          12          15          18 
0.038793103 0.016123883 0.040549170 0.124121967 0.016283525 0.040868455 
         25          30          32          40          45          50 
0.058349298 0.017001916 0.037436143 0.029054917 0.010057471 0.017720307 
         60          65          90         125 
0.008141762 0.015325670 0.015325670 0.018917625 
Code
prop.table(table(database_2025$alt1.dist_trans))

        0.5           1           2           3           4           6 
0.126454559 0.061607011 0.036934747 0.080681986 0.037671233 0.132420091 
          8           9          10          12          15          18 
0.030011784 0.017749300 0.029533068 0.125681249 0.020106054 0.055494182 
         25          30          32          40          45          50 
0.065105317 0.018706731 0.052069524 0.032920901 0.016791869 0.011415525 
         60          65          90         125 
0.016791869 0.011415525 0.010458094 0.009979378 
Code
print("SQ Distances in 2017")
[1] "SQ Distances in 2017"
Code
table(database_2017$dist_3)

 0.5    1    5   10   20   40   70  100  150 
1476 3048 1860 1728 1476  624  408  468 1440 
Code
print("SQ Distances in 2025")
[1] "SQ Distances in 2025"
Code
table(database_2025$alt3.dist)

 0.5    1    5   10   20   40   70  100  150 
2388 4992 4704 4572 3852 2724 1368 1068 1488 
Code
print("Check broadleaf 1")
[1] "Check broadleaf 1"
Code
prop.table(table(database_2025$broad_1))

        0         1 
0.7784283 0.2215717 
Code
prop.table(table(database_2017$broad_1))

        0         1 
0.7765805 0.2234195 
Code
print("Check broadleaf 2")
[1] "Check broadleaf 2"
Code
prop.table(table(database_2025$broad_2))

        0         1 
0.7493372 0.2506628 
Code
prop.table(table(database_2017$broad_2))

        0         1 
0.7517561 0.2482439 
Code
print("Check mix 1")
[1] "Check mix 1"
Code
prop.table(table(database_2025$mix_1))

        0         1 
0.3876123 0.6123877 
Code
prop.table(table(database_2017$mix_1))

       0        1 
0.390166 0.609834 
Code
print("Check mix 2")
[1] "Check mix 2"
Code
prop.table(table(database_2025$mix_2))

        0         1 
0.4444322 0.5555678 
Code
prop.table(table(database_2017$mix_2))

        0         1 
0.4450032 0.5549968 
Code
prop.table(table(database_2025$infra2_1))

        0         1 
0.7499632 0.2500368 
Code
prop.table(table(database_2017$infra2_1))

        0         1 
0.7516762 0.2483238 
Code
prop.table(table(database_2025$infra3_1))

        0         1 
0.7512888 0.2487112 
Code
prop.table(table(database_2017$infra3_1))

        0         1 
0.7481641 0.2518359 
Code
prop.table(table(database_2025$infra4_1))

       0        1 
0.749374 0.250626 
Code
prop.table(table(database_2017$infra4_1))

        0         1 
0.7500798 0.2499202 
Code
prop.table(table(database_2025$infra2_2))

        0         1 
0.7500368 0.2499632 
Code
prop.table(table(database_2017$infra2_2))

        0         1 
0.7483238 0.2516762 
Code
prop.table(table(database_2025$infra3_2))

        0         1 
0.7512888 0.2487112 
Code
prop.table(table(database_2017$infra3_2))

        0         1 
0.7481641 0.2518359 
Code
prop.table(table(database_2025$infra4_2))

   0    1 
0.75 0.25 
Code
prop.table(table(database_2017$infra4_2))

   0    1 
0.75 0.25 

Clogits

Code
stargazer(clg_2025_out, clg_2017_out, 
          type = "html", 
          column.labels = c("2025", "2017"),
          title = "Comparison of Models (2025 vs 2017)")
Comparison of Models (2025 vs 2017)
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
type_broad -0.543 1.935 -0.281 3.247 -0.167
type_mix 1.033 2.129 0.485 3.284 0.314
species 14.729 0.981 15.012 1.755 8.391
height 2.439 0.168 14.557 0.253 9.655
age_two -8.542 1.822 -4.687 3.212 -2.660
age_multi 8.609 1.797 4.790 3.105 2.772
deadwood_med 3.550 1.535 2.313 2.400 1.479
deadwood_high 11.887 1.581 7.521 2.405 4.943
infrastr2 3.513 1.852 1.897 2.779 1.264
infrastr3 18.339 1.596 11.487 2.962 6.191
infrastr4 40.556 1.845 21.977 3.558 11.399
dist -0.013 0.0003 -39.317 0.001 -17.262
ASC_sq 125.566 4.405 28.506 8.484 14.800
Comparison of Models (2025 vs 2017)
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
type_broad 1.181 3.279 0.360 4.882 0.242
type_mix 6.663 3.451 1.931 5.171 1.288
species 11.942 1.488 8.025 2.629 4.543
height 2.814 0.280 10.055 0.441 6.387
age_two 0.718 3.187 0.225 5.044 0.142
age_multi 25.370 2.978 8.518 5.213 4.867
deadwood_med 3.253 2.575 1.263 3.676 0.885
deadwood_high 15.399 2.619 5.879 3.822 4.029
infrastr2 -6.279 3.230 -1.944 4.333 -1.449
infrastr3 22.950 2.493 9.207 4.708 4.875
infrastr4 39.910 2.767 14.422 5.264 7.581
dist 0.014 0.0004 30.968 0.001 11.721
ASC_sq 82.378 2.778 29.656 7.485 11.006
Code
html_2025 <- capture.output(
  stargazer(clg_2025_out, type = "html", title = "2025", column.labels = "2025")
)

html_2017 <- capture.output(
  stargazer(clg_2017_out, type = "html", title = "2017", column.labels = "2017")
)

cat('<div style="display: flex; gap: 20px;">')
Code
cat('<div style="flex: 1;">', paste(html_2025, collapse = "\n"), '</div>')
2025
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
type_broad -0.543 1.935 -0.281 3.247 -0.167
type_mix 1.033 2.129 0.485 3.284 0.314
species 14.729 0.981 15.012 1.755 8.391
height 2.439 0.168 14.557 0.253 9.655
age_two -8.542 1.822 -4.687 3.212 -2.660
age_multi 8.609 1.797 4.790 3.105 2.772
deadwood_med 3.550 1.535 2.313 2.400 1.479
deadwood_high 11.887 1.581 7.521 2.405 4.943
infrastr2 3.513 1.852 1.897 2.779 1.264
infrastr3 18.339 1.596 11.487 2.962 6.191
infrastr4 40.556 1.845 21.977 3.558 11.399
dist -0.013 0.0003 -39.317 0.001 -17.262
ASC_sq 125.566 4.405 28.506 8.484 14.800
Code
cat('<div style="flex: 1;">', paste(html_2017, collapse = "\n"), '</div>')
2017
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
type_broad 1.181 3.279 0.360 4.882 0.242
type_mix 6.663 3.451 1.931 5.171 1.288
species 11.942 1.488 8.025 2.629 4.543
height 2.814 0.280 10.055 0.441 6.387
age_two 0.718 3.187 0.225 5.044 0.142
age_multi 25.370 2.978 8.518 5.213 4.867
deadwood_med 3.253 2.575 1.263 3.676 0.885
deadwood_high 15.399 2.619 5.879 3.822 4.029
infrastr2 -6.279 3.230 -1.944 4.333 -1.449
infrastr3 22.950 2.493 9.207 4.708 4.875
infrastr4 39.910 2.767 14.422 5.264 7.581
dist 0.014 0.0004 30.968 0.001 11.721
ASC_sq 82.378 2.778 29.656 7.485 11.006
Code
cat('</div>')
Code
ggplot(filter(ci_data, Group == "wtp"), aes(x = Coefficient, y = Mean, color = Model)) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTT Estimates with 95% Confidence Intervals",
    x = "Coefficient",
    y = "WTT Estimate (km)",
    color = "Model"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Code
ci_data_com <- ci_data %>% filter(!grepl("^ASC", Coefficient))

ggplot(filter(ci_data_com, Group == "wtp_first_vs_second"), aes(x = Coefficient, y = Mean, color = Model)) +
    geom_rect(data = stripe_data[1:6, ],
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "gray96", inherit.aes = FALSE) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTT Estimates with 95% Confidence Intervals First vs Second Choice",
    x = "Coefficient",
    y = "WTT Estimate (km)",
    color = "Model"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Mixed Logits

Code
stargazer(mxl_2025_out, 
          type = "html", 
          title = "Mixed Logit Model Output (2025) WTP Space",
          column.labels = "2025")
Mixed Logit Model Output (2025) WTP Space
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
beta_type_broad 4.678 2.755 1.698 2.502 1.870
beta_type_mix 8.954 2.891 3.097 3.083 2.904
beta_age_multi 7.718 2.067 3.733 2.149 3.591
beta_age_two 4.435 2.038 2.176 2.061 2.152
beta_deadwood_high 4.564 1.773 2.574 1.602 2.850
beta_deadwood_med 4.262 1.857 2.295 1.828 2.332
beta_height 0.942 0.166 5.659 0.194 4.869
beta_infrastr2 7.986 2.668 2.993 3.325 2.401
beta_infrastr3 8.670 2.365 3.665 2.900 2.990
beta_infrastr4 16.479 2.542 6.483 3.456 4.767
beta_species 2.695 0.817 3.299 0.619 4.356
beta_ASC_sq 59.160 5.833 10.143 9.542 6.200
beta_dist -2.904 0.127 -22.821 0.198 -14.674
sig_type_broad -7.703 2.381 -3.236 2.307 -3.339
sig_type_mix -4.586 1.683 -2.725 1.060 -4.325
sig_age_multi 7.637 1.823 4.189 1.826 4.182
sig_age_two 0.081 1.327 0.061 0.810 0.100
sig_deadwood_high -2.099 1.265 -1.659 0.828 -2.534
sig_deadwood_med -4.905 1.696 -2.892 1.345 -3.646
sig_height -0.273 0.087 -3.148 0.091 -3.001
sig_infrastr2 9.162 2.978 3.076 2.719 3.370
sig_infrastr3 4.521 1.576 2.868 1.821 2.483
sig_infrastr4 -11.718 3.676 -3.188 5.629 -2.082
sig_species 4.079 1.273 3.203 1.508 2.706
sig_ASC_sq 49.781 4.375 11.380 8.029 6.200
sig_dist 1.122 0.151 7.415 0.233 4.825
Code
stargazer(mxl_2017_out, 
          type = "html", 
          title = "Mixed Logit Model Output (2017) WTP Space",
          column.labels = "2017")
Mixed Logit Model Output (2017) WTP Space
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
beta_type_broad 1.517 0.858 1.769 1.132 1.341
beta_type_mix 2.314 0.842 2.748 0.995 2.327
beta_age_multi 2.098 0.740 2.835 0.798 2.630
beta_age_two -1.199 0.807 -1.485 1.027 -1.167
beta_deadwood_high 1.589 0.572 2.778 0.555 2.861
beta_deadwood_med 1.422 0.578 2.460 0.544 2.613
beta_height 0.948 0.091 10.452 0.153 6.205
beta_infrastr2 0.790 0.827 0.955 0.914 0.864
beta_infrastr3 6.982 0.794 8.795 1.233 5.664
beta_infrastr4 9.393 0.855 10.982 1.507 6.232
beta_species 2.398 0.396 6.060 0.500 4.797
beta_ASC_sq 17.237 1.167 14.771 2.379 7.246
beta_dist 0.100 0.005 19.455 0.011 9.495
sig_type_broad 1.028 2.082 0.494 3.422 0.301
sig_type_mix -0.235 1.207 -0.194 1.188 -0.197
sig_age_multi 2.055 1.590 1.292 2.260 0.909
sig_age_two 0.244 1.379 0.177 1.647 0.148
sig_deadwood_high 1.126 1.114 1.011 1.065 1.057
sig_deadwood_med -0.137 1.553 -0.088 1.950 -0.070
sig_height 0.846 0.090 9.409 0.159 5.315
sig_infrastr2 4.128 1.420 2.907 1.504 2.745
sig_infrastr3 5.118 1.133 4.517 1.565 3.270
sig_infrastr4 5.847 1.202 4.864 1.736 3.368
sig_species 1.581 0.959 1.648 1.797 0.880
sig_ASC_sq 23.723 1.357 17.476 3.462 6.853
sig_dist -0.082 0.005 -17.193 0.010 -8.482
Code
ci_data_mod <- ci_data %>% filter(Model == "2017" | Model == "2025")

ggplot(filter(ci_data_mod, Group == "mxl"), aes(x = Coefficient, y = Mean, color = Model)) +
  geom_rect(data = stripe_data[1:13, ],
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "gray96", inherit.aes = FALSE) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTT Estimates with 95% Confidence Intervals",
    x = "Coefficient",
    y = "WTT Estimate (km)",
    color = "Model"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Code
ci_data_mod2 <- ci_data %>%
  filter(str_starts(Coefficient, "beta"))

ggplot(filter(ci_data_mod2, Group == "mxl_17_vs_25"), aes(x = Coefficient, y = Mean, color = Model)) +
  geom_rect(data = stripe_data[1:8, ],
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "gray96", inherit.aes = FALSE) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTT Estimates with 90% Confidence Intervals",
    x = "Coefficient",
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  theme_minimal() +
  scale_color_manual(values = c("red", "blue", "forestgreen", "black")) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = c(1, 1),
    legend.justification = c(1, 1),
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) + scale_x_discrete(labels = function(x) sub("^beta_", "", x))

Drought Models

Actual forest loss

Code
ci_data_mod3 <- ci_data_mod2 %>%
  filter(Group == "mxl_2025_drought") %>%
  mutate(
    Model = factor(
      Model,
      levels = c(
        "2025 severe drought area",
        "2025 drought area",
        "2025 full model",
        "2025 low drought area",
        "2025 zero drought area"
        )
      )
    )

ggplot(filter(ci_data_mod3, Group == "mxl_2025_drought"), aes(x = Coefficient, y = Mean, color = Model)) +
  geom_rect(data = stripe_data[1:8, ],
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "gray96", inherit.aes = FALSE) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTP Estimates with 90% Confidence Intervals",
    x = "Coefficient",
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  theme_minimal() +
  #coord_flip() +
  scale_color_manual(values = c("darkred", "red", "grey", "forestgreen","lightgreen")) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = c(1, 1),
    legend.justification = c(1, 1),
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) + scale_x_discrete(labels = function(x) sub("^beta_", "", x))

Code
all_drought_data <- all_drought_data %>% 
  filter(str_starts(Coefficient, "beta")) %>% 
  mutate(
    Model = factor(
      Model,
      levels = c(
        "2017 no drought area",
        "2025 no drought area",
        "2017 drought area",
        "2025 drought area"
      )
    )
  )

ggplot(filter(all_drought_data, Group == "mxl_17_25_drought"), aes(x = Coefficient, y = Mean, color = Model)) +
  geom_rect(data = stripe_data[1:8, ],
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "gray96", inherit.aes = FALSE) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTP Estimates with 90% Confidence Intervals",
    x = "Coefficient",
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  theme_minimal() +
  #coord_flip() +
  scale_color_manual(values = c("red",  "darkred", "yellow3", "yellow4")) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = c(1, 1),
    legend.justification = c(1, 1),
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) + scale_x_discrete(labels = function(x) sub("^beta_", "", x))

Code
model_levels <- c("2017 no drought area",
                  "2025 no drought area",
                  "2017 drought area",
                  "2025 drought area")

dat_faceted <- all_drought_data 

# Stripes over MODEL slots inside each facet
stripe_models <- data.frame(
  xmin = seq(0.5, length(model_levels) - 0.5, by = 2),
  xmax = seq(1.5, length(model_levels) + 0.5, by = 2),
  ymin = -Inf, ymax = Inf
)

# Your palette
cols <- c(
  "2017 no drought area" = "red",
  "2025 no drought area" ="darkred",
  "2017 drought area" = "yellow3",
  "2025 drought area" = "yellow4"
)

p_facets <- ggplot(dat_faceted, aes(x = Model, y = Mean, color = Model)) +
  geom_rect(data = stripe_models,
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            inherit.aes = FALSE, fill = "gray96") +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.15, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  facet_wrap(~ Coefficient, scales = "free_y") +
  labs(
    title = "WTP Estimates with 90% Confidence Intervals",
    x = NULL,
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  scale_color_manual(values = cols) +
  theme_minimal() +
  theme(
    axis.text.x  = element_blank(),   # hide x labels
    axis.ticks.x = element_blank(),   # hide x ticks
    legend.position = "bottom",       # legend underneath
    legend.justification = "center",
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) +
  guides(color = guide_legend(nrow = 1, byrow = TRUE))  # single-row legend

p_facets

Code
ggplot(contrasts, aes(x = area, y = diff, color = area)) +
  geom_hline(yintercept = 0, linewidth = 0.4, linetype = "dashed", color = "grey40") +
  geom_pointrange(aes(ymin = ci_lo, ymax = ci_hi),
                  position = position_dodge(width = 0.4),
                  linewidth = 0.7) +
  facet_wrap(~ term, scales = "free_y") +
  scale_color_manual(values = c("No drought" = "forestgreen",
                                "Drought"    = "red")) +
  labs(
    title = "Year difference (2025 − 2017) by coefficient",
    subtitle = "Points and 90% robust CIs shown for each area",
    x = NULL, y = "Difference in coefficient"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_text(angle = 0, hjust = 0.5),
    legend.position = "bottom"
  )

Code
ggplot(did_df1, aes(x = term, y = did, color = sig)) +
  geom_hline(yintercept = 0, linewidth = 0.4, linetype = "dashed", color = "grey40") +
  geom_pointrange(aes(ymin = ci_lo, ymax = ci_hi), linewidth = 0.7) +
  coord_flip() +
  scale_color_manual(values = c("Significant" = "red", "Not significant" = "black")) +
  labs(
    title = "Difference-in-differences: (Drought − No drought) of (2025 − 2017)",
    subtitle = "Points and 90% robust CIs; red = p < 0.05",
    x = NULL,
    y = "Difference-in-differences",
    color = "Significance at 5% level"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_text(angle = 0, hjust = 0.5),
    legend.position = "bottom"
  ) +
  scale_x_discrete(labels = function(x) sub("^beta_", "", x))

Code
#####
model_levels <- c("2025 severe drought area",
                  "2025 drought area",
                  "2025 low drought area",
                  "2025 zero drought area")

dat_faceted <- ci_data_mod2 %>%
  filter(Group == "mxl_2025_drought") %>%
  mutate(Model = factor(Model, levels = model_levels)) %>% 
  filter(Model == "2025 severe drought area" | Model == "2025 zero drought area")

# Stripes over MODEL slots inside each facet
stripe_models <- data.frame(
  xmin = seq(0.5, length(model_levels) - 0.5, by = 2),
  xmax = seq(1.5, length(model_levels) + 0.5, by = 2),
  ymin = -Inf, ymax = Inf
)

# Your palette
cols <- c(
  "2025 severe drought area" = "red",
  "2025 zero drought area"    = "forestgreen"
)

p_facets <- ggplot(dat_faceted, aes(x = Model, y = Mean, color = Model)) +
  geom_rect(data = stripe_models,
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            inherit.aes = FALSE, fill = "gray96") +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.15, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  facet_wrap(~ Coefficient, scales = "free_y") +
  labs(
    title = "WTP Estimates with 90% Confidence Intervals",
    x = NULL,
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  scale_color_manual(values = cols) +
  theme_minimal() +
  theme(
    axis.text.x  = element_blank(),   # hide x labels
    axis.ticks.x = element_blank(),   # hide x ticks
    legend.position = "bottom",       # legend underneath
    legend.justification = "center",
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) +
  guides(color = guide_legend(nrow = 1, byrow = TRUE))  # single-row legend

p_facets

Forest loss around place of residence

Code
ggplot(filter(ci_data_mod2, Group == "mxl_25_10km"), aes(x = Coefficient, y = Mean,
                                                         color = factor(Model, levels=c("2025 low", "2025 middle",
                                                                           "2025 high")))) +
  geom_rect(data = stripe_data[1:8, ],
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "gray96", inherit.aes = FALSE) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTT Estimates with 90% Confidence Intervals",
    x = "Coefficient",
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  theme_minimal() +
  scale_color_manual(values = c("blue", "gray70", "red")) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = c(0.2, 1),
    legend.justification = c(1, 1),
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) + scale_x_discrete(labels = function(x) sub("^beta_", "", x)) + coord_trans(y = "pseudo_log")

Code
p_facets3

Code
ggplot(contrasts2, aes(x = area, y = diff, color = area)) +
  geom_hline(yintercept = 0, linewidth = 0.4, linetype = "dashed", color = "grey40") +
  geom_pointrange(aes(ymin = ci_lo, ymax = ci_hi),
                  position = position_dodge(width = 0.4),
                  linewidth = 0.7) +
  facet_wrap(~ term, scales = "free_y") +
  scale_color_manual(values = c("low" = "blue",
                                "middle" = "gray70",
                                "high"    = "red")) +
  labs(
    title = "Year difference (2025 − 2017) by coefficient",
    subtitle = "Points and 90% robust CIs shown for each area",
    x = NULL, y = "Difference in coefficient"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_text(angle = 0, hjust = 0.5),
    legend.position = "bottom"
  )

Code
ggplot(did_df, aes(x = term, y = did, color = sig)) +
  geom_hline(yintercept = 0, linewidth = 0.4, linetype = "dashed", color = "grey40") +
  geom_pointrange(aes(ymin = ci_lo, ymax = ci_hi), linewidth = 0.7) +
  coord_flip() +
  scale_color_manual(values = c("Significant" = "red", "Not significant" = "black")) +
  labs(
    title = "Difference-in-differences: (High − Low) of (2025 − 2017)",
    subtitle = "Points and 90% robust CIs; red = p < 0.05",
    x = NULL,
    y = "Difference-in-differences",
    color = "Significance at 5% level"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_text(angle = 0, hjust = 0.5),
    legend.position = "bottom"
  ) +
  scale_x_discrete(labels = function(x) sub("^beta_", "", x)) 

Perceived drought

Code
ggplot(filter(ci_data_mod2, Group == "mxl_2025_perceived"), aes(x = Coefficient, y = Mean, color = Model)) +
  geom_rect(data = stripe_data[1:8, ],
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "gray96", inherit.aes = FALSE) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTT Estimates with 90% Confidence Intervals",
    x = "Coefficient",
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  theme_minimal() +
  scale_color_manual(values = c("red",  "forestgreen")) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = c(1, 1),
    legend.justification = c(1, 1),
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) + scale_x_discrete(labels = function(x) sub("^beta_", "", x))

Code
ggsave("figures/perceived_low_high.png", width=9, height=5, dpi="print")

#####
model_levels <- c("2025 high perceived drought",
                  "2025 low perceived drought")

dat_faceted <- ci_data_mod2 %>%
  filter(Group == "mxl_2025_perceived") %>%
  mutate(Model = factor(Model, levels = model_levels))


cols <- c(
  "2025 high perceived drought" = "red",
  "2025 low perceived drought" = "forestgreen"
)

p_facets <- ggplot(dat_faceted, aes(x = Model, y = Mean, color = Model)) +
  geom_rect(data = stripe_models,
            aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            inherit.aes = FALSE, fill = "gray96") +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.15, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  facet_wrap(~ Coefficient, scales = "free_y") +
  labs(
    title = "WTT Estimates with 90% Confidence Intervals",
    x = NULL,
    y = "WTT (km/unit change)",
    color = "Model"
  ) +
  scale_color_manual(values = cols) +
  theme_minimal() +
  theme(
    axis.text.x  = element_blank(),   # hide x labels
    axis.ticks.x = element_blank(),   # hide x ticks
    legend.position = "bottom",       # legend underneath
    legend.justification = "center",
    legend.background = element_rect(fill = alpha("white", 0.7), colour = "black")
  ) +
  guides(color = guide_legend(nrow = 1, byrow = TRUE))  # single-row legend

p_facets

Drought Questions

Code
attr(data_2025_complete$A1, "label")
[1] "A1. Have the forest areas that you regularly visit changed in the last 10 years?"
Code
attr(data_2025_complete$A1, "labels")
NULL
Code
table(data_2025_complete$A1)

  1   2   3   4 
475 567 781 440 
Code
ggplot(data = data_2025_complete) +
  geom_bar(aes(x = as.factor(A1), y = after_stat(count / sum(count))),
           position = "dodge") +
  scale_y_continuous(labels = scales::percent) +
  labs(
    title = "Has forest changed in last 10 years \n(1=No, 2=Improved, 3=Deteriorated, 4=Can't tell)?",
    x = "",
    y = "Percent"
  ) +
  theme_minimal()

Code
attr(data_2025_complete$A2, "label")
[1] "A2. Did you notice signs of drought damage during your last visit to the forest?"
Code
attr(data_2025_complete$A2, "labels")
NULL
Code
table(data_2025_complete$A2)

  1   2   3   4   5 
387 964 436 378  98 
Code
ggplot(data = data_2025_complete) +
  geom_bar(aes(x = as.factor(A2), y = after_stat(count / sum(count))),
           position = "dodge") +
  scale_y_continuous(labels = scales::percent) +
  labs(
    title = "Visible drought damages last forest visit (yes (1) to no (5))?",
    x = "",
    y = "Percent"
  ) +
  theme_minimal()

Code
attr(data_2025_complete$A3, "label")
[1] "A3. Do you have the impression, regardless of your last visit to the forest, that the forests in your region are increasingly affected by drought damage?"
Code
attr(data_2025_complete$A3, "labels")
NULL
Code
table(data_2025_complete$A3)

  1   2   3   4   5 
358 997 456 362  90 
Code
ggplot(data = data_2025_complete) +
  geom_bar(aes(x = as.factor(A3), y = after_stat(count / sum(count))),
           position = "dodge") +
  scale_y_continuous(labels = scales::percent) +
  labs(
    title = "Perception of drought damages in region (yes (1) to no (5))?",
    x = "",
    y = "Percent"
  ) +
  theme_minimal()

Code
attr(data_2025_complete$A6, "label")
[1] "A6. Have you changed the frequency of your forest visits due to drought damage?"
Code
attr(data_2025_complete$A6, "labels")
NULL
Code
table(data_2025_complete$A6)

  1   2   3   4   5   6 
  9  71 672 102  33 187 
Code
ggplot(data = data_2025_complete %>% filter(!is.na(A6) & A6 != 6)) +
  geom_bar(aes(x = as.factor(A6), y = after_stat(count / sum(count))),
           position = "dodge") +
  scale_y_continuous(labels = scales::percent) +
  labs(
    title = "Changed forest visiting frequency because of drought \n(1=Less often, 3=Unchanged, 5=More often)?",
    x = "",
    y = "Percent"
  ) +
  theme_minimal()

Code
attr(data_2025_complete$A8, "label")
[1] "A8. Have you changed the forest areas you usually visit because of drought damage?"
Code
attr(data_2025_complete$A8, "labels")
NULL
Code
table(data_2025_complete$A8)

  1   2 
193 881 
Code
ggplot(data = data_2025_complete %>% filter(!is.na(A8))) +
  geom_bar(aes(x = as.factor(A8), y = after_stat(count / sum(count))),
           position = "dodge") +
  scale_y_continuous(labels = scales::percent) +
  labs(
    title = "Changed forest ares because of drought (1=Yes, 2=No)?",
    x = "",
    y = "Percent"
  ) +
  theme_minimal()

Code
attr(data_2025_complete$A13, "label")
[1] "A13. How many trees in German forests do you estimate are currently affected by natural events such as drought, storms and bark beetle infestations?"
Code
attr(data_2025_complete$A13, "labels")
NULL
Code
ggplot(data=data_2025_complete) +
  geom_bar(aes(x = as.factor(A13)), position = "dodge") +
  labs(title = "How much trees are sick?", x = "", y = "Count") +
  theme_minimal()

Code
pal <- colorBin(
  palette = c("red", "yellow", "green"),
  bins = c(0.5, 2.5, 3.5, 5.5),  # edges: (0.5–2.5], (2.5–3.5], (3.5–5.5]
  domain = c(1, 2, 3, 4, 5),
  right = TRUE  # ensures e.g. 2.0 falls into red, 3.0 into yellow, 5.0 into green
)

leaflet(data_2025_complete) %>%
  addProviderTiles("OpenStreetMap") %>%
  addCircleMarkers(
    radius = 5,
    fillColor = ~pal(A2),
    fillOpacity = 0.7,
    color = "#444444",
    weight = 0.5,
  ) %>%
  addLegend(
    "bottomright",
    pal = pal,
    values = ~A2,
    title = "Drought Index (last visit)",
    opacity = 0.7
  )
Code
leaflet(data_2025_complete) %>%
  addProviderTiles("OpenStreetMap") %>%
  addCircleMarkers(
    radius = 5,
    fillColor = ~pal(A3),
    fillOpacity = 0.7,
    color = "#444444",
    weight = 0.5,
  ) %>%
  addLegend(
    "bottomright",
    pal = pal,
    values = ~A3,
    title = "Drought Index (general)",
    opacity = 0.7
  )

Forest Owners

Code
table(data_2025_complete$EIG1)

   1    2    3 
 152 2082   29 
Code
table(data_2025_complete$EIG2_1)

   0    1    2    3    4    5    6    9   10   11   12   15   20   21   30   34 
   2   11   14    8    4   14    3    1    4    1    7    3    4    1    1    1 
  50  100  125  200  210  250  300 1000 
   3    1    1    6    1    2    6    1 
Code
table(data_2025_complete$EIG3_1)

   0    1    2    3    5    6   10   11   12   15   20   22   30   50   80  100 
  17    2    7    4    6    3    7    1    1    1    7    1    3    3    1    3 
 120  125  180  200  250  300  500 1000 
   1    1    1    7    1    2    2    2 

Check trees and leaves comparison

Code
check_pair_responses <- function(data, type = c("LEAVES", "TREES"), n_pairs = 5) {
  type <- match.arg(type)
  
  # Inner function for one comparison
  check_one <- function(i) {
    prefix <- paste0("PAIR", type, "_", i)
    show_col <- paste0("SHOWPAIR", type, "_", i)
    
    data %>%
      select(all_of(c(paste0(prefix, "_1"), paste0(prefix, "_2"), show_col))) %>%
      rename(left = 1, right = 2, answer = 3) %>%
      mutate(comparison = i) %>%
      separate(left, into = c("left_id", NA), sep = ",", remove = FALSE) %>%
      separate(right, into = c("right_id", NA), sep = ",", remove = FALSE) %>%
      mutate(
        answer = as.character(answer),
        valid_answer = answer %in% c(left_id, right_id, "99", NA)
      ) %>%
      select(comparison, answer, left_id, right_id, valid_answer)
  }
  
  # Apply to all comparisons
  purrr::map_dfr(1:n_pairs, check_one)
}

leaf_check <- check_pair_responses(data_2025_complete, type = "LEAVES", n_pairs = 5)
tree_check <- check_pair_responses(data_2025_complete, type = "TREES", n_pairs = 5)

leaf_check %>% filter(!valid_answer)
Simple feature collection with 0 features and 5 fields
Bounding box:  xmin: NA ymin: NA xmax: NA ymax: NA
Geodetic CRS:  WGS 84
# A tibble: 0 × 6
# ℹ 6 variables: comparison <int>, answer <chr>, left_id <chr>, right_id <chr>,
#   valid_answer <lgl>, geometry <GEOMETRY [°]>
Code
tree_check %>% filter(!valid_answer)
Simple feature collection with 0 features and 5 fields
Bounding box:  xmin: NA ymin: NA xmax: NA ymax: NA
Geodetic CRS:  WGS 84
# A tibble: 0 × 6
# ℹ 6 variables: comparison <int>, answer <chr>, left_id <chr>, right_id <chr>,
#   valid_answer <lgl>, geometry <GEOMETRY [°]>
Code
head(leaf_check)
Simple feature collection with 6 features and 5 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 6.918211 ymin: 47.62293 xmax: 14.41544 ymax: 51.46891
Geodetic CRS:  WGS 84
# A tibble: 6 × 6
  comparison answer left_id right_id valid_answer            geometry
       <int> <chr>  <chr>   <chr>    <lgl>                <POINT [°]>
1          1 <NA>   ""      ""       TRUE         (8.037809 51.46891)
2          1 23     "23"    "35"     TRUE         (6.918211 51.01328)
3          1 <NA>   ""      ""       TRUE         (14.41544 51.17283)
4          1 <NA>   ""      ""       TRUE          (13.0199 47.62293)
5          1 61     "61"    "33"     TRUE          (11.1573 49.63228)
6          1 8      "8"     "81"     TRUE         (9.052563 51.20278)
Code
head(tree_check)
Simple feature collection with 6 features and 5 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 6.918211 ymin: 47.62293 xmax: 14.41544 ymax: 51.46891
Geodetic CRS:  WGS 84
# A tibble: 6 × 6
  comparison answer left_id right_id valid_answer            geometry
       <int> <chr>  <chr>   <chr>    <lgl>                <POINT [°]>
1          1 <NA>   ""      ""       TRUE         (8.037809 51.46891)
2          1 1      "75"    "1"      TRUE         (6.918211 51.01328)
3          1 <NA>   ""      ""       TRUE         (14.41544 51.17283)
4          1 <NA>   ""      ""       TRUE          (13.0199 47.62293)
5          1 43     "79"    "43"     TRUE          (11.1573 49.63228)
6          1 75     "75"    "49"     TRUE         (9.052563 51.20278)

Analyse forest loss

Code
library(tidyterra)
points_sf <- data_2025_complete  # assuming this is an sf object

points_sf <- st_transform(points_sf, crs = crs(forest_loss))


points_in_raster_extent <- points_sf[
  st_within(points_sf, st_as_sfc(st_bbox(forest_loss)), sparse = FALSE), ]

ggplot() +
  geom_spatraster(data = forest_loss_100) +
  scale_fill_viridis_c(na.value = "transparent", name = "Forest Loss", trans="sqrt") +
  geom_sf(data = points_in_raster_extent, aes(color = A3), size = 1) +
  scale_color_viridis_c(name = "Drought Index", direction = -1, option = "A") +
  theme_minimal() +
  labs(title = "Forest Loss and Drought Index in Germany (100x100m resolution)") +
  coord_sf()

Code
ggplot() +
  geom_spatraster(data = forest_loss_1km) +
  scale_fill_viridis_c(na.value = "transparent", name = "Forest Loss", trans="sqrt") +
  geom_sf(data = points_in_raster_extent, aes(color = A3), size = 1) +
  scale_color_viridis_c(name = "Drought Index", direction = -1, option = "A") +
  theme_minimal() +
  labs(title = "Forest Loss and Drought Index in Germany (1x1km resolution)") +
  coord_sf()

Code
ggplot(data=data_2025_complete) + 
  geom_point(aes(x=forest_loss_visit_1km, y=dead_share_of_forest_5000, col=for_dis)) +
  labs(x="Dead forest share within 1km×1km cell of forest visit (%)", y="Share of dead forest within 5km radius around place of residence (%)") 

Code
ggplot(data=data_2025_complete) + 
  geom_point(aes(x=forest_loss_visit_1km, y=dead_share_of_forest_10000, col=for_dis)) +
  labs(x="Dead forest share within 1km×1km cell of forest visit (%)", y="Share of dead forest within 10km radius around place of residence (%)") 

Code
ggplot(data=data_2025_complete) + 
  geom_point(aes(x=forest_loss_visit_1km, y=dead_share_of_forest_15000, col=for_dis)) +
  labs(x="Dead forest share within 1km×1km cell of forest visit (%)", y="Share of dead forest within 15km radius around place of residence (%)") 

Code
ggplot(data=data_2025_complete) + 
    geom_point(aes(x=dead_share_of_forest_15000, y=dead_share_of_forest_5000, col=for_dis)) +
    labs(x="Share of dead forest within 15km radius around place of residence (%)", y="Share of dead forest within 5km radius around place of residence (%)") 

Code
tab3 <- data_2025_complete %>%
  count(fl_lv_third, fl_por_5) %>%
  group_by(fl_lv_third) %>%
  mutate(share = n / sum(n))

ggplot(tab3, aes(x = fl_por_5, y = fl_lv_third, fill = share)) +
  geom_tile() +
  geom_text(aes(label = scales::percent(share, accuracy = 1)), color = "black", size = 3) +
  scale_fill_viridis_c(name = "Share within residence\nforest-loss level", labels = scales::percent) +
  labs(
    x = "Forest loss (place of residence 5km radius)",
    y = "Forest loss (last visited forest 1kmx1km cell)",
    title = "Relative distribution of forest-loss categories"
  ) +
  theme_minimal(base_size = 12)

Code
tab <- data_2025_complete %>%
  count(fl_lv_third, fl_por_10) %>%
  group_by(fl_lv_third) %>%
  mutate(share = n / sum(n))

ggplot(tab, aes(x = fl_por_10, y = fl_lv_third, fill = share)) +
  geom_tile() +
  geom_text(aes(label = scales::percent(share, accuracy = 1)), color = "black", size = 3) +
  scale_fill_viridis_c(name = "Share within residence\nforest-loss level", labels = scales::percent) +
  labs(
    x = "Forest loss (place of residence 10km radius)",
    y = "Forest loss (last visited forest 1kmx1km cell)",
    title = "Relative distribution of forest-loss categories"
  ) +
  theme_minimal(base_size = 12)

Code
tab2 <- data_2025_complete %>%
  count(fl_lv_third, fl_por_15) %>%
  group_by(fl_lv_third) %>%
  mutate(share = n / sum(n))

ggplot(tab2, aes(x = fl_por_15, y = fl_lv_third, fill = share)) +
  geom_tile() +
  geom_text(aes(label = scales::percent(share, accuracy = 1)), color = "black", size = 3) +
  scale_fill_viridis_c(name = "Share within residence\nforest-loss level", labels = scales::percent) +
  labs(
    x = "Forest loss (place of residence 15km radius)",
    y = "Forest loss (last visited forest 1kmx1km cell)",
    title = "Relative distribution of forest-loss categories"
  ) +
  theme_minimal(base_size = 12)

Code
tab_17 <- data_2017_complete %>%
  filter(!is.na(fl_lv_third), !is.na(fl_por_10)) %>%
  count(fl_lv_third, fl_por_10) %>%
  group_by(fl_lv_third) %>%
  mutate(share = n / sum(n))

ggplot(tab_17, aes(x = fl_por_10, y = fl_lv_third, fill = share)) +
  geom_tile() +
  geom_text(aes(label = scales::percent(share, accuracy = 1)), color = "black", size = 3) +
  scale_fill_viridis_c(name = "Share within residence\nforest-loss level", labels = scales::percent) +
  labs(
    x = "Forest loss (place of residence 10km radius)",
    y = "Forest loss (last visited forest 1kmx1km cell)",
    title = "Relative distribution of forest-loss categories in 2017"
  ) +
  theme_minimal(base_size = 12)

Code
tab_fil <- data_2025_complete %>% filter(for_dis <= 4) %>% 
  count(fl_lv_third, fl_por_5) %>%
  group_by(fl_lv_third) %>%
  mutate(share = n / sum(n))

ggplot(tab_fil, aes(x = fl_por_5, y = fl_lv_third, fill = share)) +
  geom_tile() +
  geom_text(aes(label = scales::percent(share, accuracy = 1)), color = "black", size = 3) +
  scale_fill_viridis_c(name = "Share within residence\nforest-loss level", labels = scales::percent) +
  labs(
    x = "Forest loss (place of residence 5km radius)",
    y = "Forest loss (last visited forest 1kmx1km cell)",
    title = "Relative distribution of forest-loss categories (travel distance below 20km)"
  ) +
  theme_minimal(base_size = 12)

Code
data_2025_complete_ger <- data_2025_complete %>% filter(flag_out_germany == 0)

ggplot(data_2025_complete_ger) +
    geom_sf(data = germany_fed, fill = NA, color = "grey50") +
    geom_sf(aes(geometry = geometry_depart, color = dead_share_of_forest_5000), size = 1) +
    scale_color_viridis_c(
        trans = "log1p",                    # handles zeros: log(1 + x)
        labels = scales::label_percent(accuracy = 1),
        breaks = c(0, .02, .05, .1, .2, 03, .4, 0.5)
    ) +
    guides(color = guide_colorbar(title = "Dead forest share (%)",
           barheight = unit(10, "cm")))

Code
ggplot(data_2025_complete_ger) +
    geom_sf(data = germany_fed, fill = NA, color = "grey50") +
    geom_sf(aes(geometry = geometry_depart, color = as.factor(fl_por_10)), size = 1) +
    labs(color="Groups") +
    scale_color_manual(values = c("blue", "gray70", "red"),
                       labels = c("low", "medium", "high")) 

Code
tab31 <- database_2025 %>%
    count(fl_lv_third, alt3.deadwood) %>%
    group_by(fl_lv_third) %>%
    mutate(share = n / sum(n))

ggplot(tab31, aes(x = alt3.deadwood, y = fl_lv_third, fill = share)) +
    geom_tile() +
    geom_text(aes(label = scales::percent(share, accuracy = 1)), color = "black", size = 3) +
    scale_fill_viridis_c(name = "Share", labels = scales::percent) +
    labs(
        x = "Deadwood in forest (reported)",
        y = "Forest loss (last visited forest 1kmx1km cell)",
        title = "Relative distribution of forest-loss categories"
    ) +
    theme_minimal(base_size = 12)

Code
tab31 <- database_2025 %>%
  count(fl_lv_third, alt3.deadwood) %>%
  mutate(share = n / sum(n))  # no group_by before this

ggplot(tab31, aes(x = alt3.deadwood, y = fl_lv_third, fill = share)) +
  geom_tile() +
  geom_text(aes(label = scales::percent(share, accuracy = 1)), color = "black", size = 3) +
  scale_fill_viridis_c(name = "Share", labels = scales::percent) +
  labs(
    x = "Deadwood in forest (reported)",
    y = "Forest loss (last visited forest 1kmx1km cell)",
    title = "Relative distribution of forest-loss categories (global 100%)"
  ) +
  theme_minimal(base_size = 12)

Code
# ggplot() +
#   geom_violin(data = final_2017_merged,
#               aes(x = "2017", y = forest_loss1, fill = "2017"),
#               alpha = 0.6, color = "darkorange3") +
#   geom_violin(data = final_2025_merged,
#               aes(x = "2025", y = forest_loss,  fill = "2025"),
#               alpha = 0.6, color = "darkgreen") +
#   scale_fill_manual(name = "Sample year",
#                     values = c("2017" = "orange", "2025" = "forestgreen")) +
#   theme_minimal(base_size = 14) +
#   labs(title = "Distribution of (Hypothetical) Forest Loss (2017 vs 2025)",
#        x = "", y = "Forest Loss within 1km×1km Cell")
Code
points_vect <- vect(points_sf)

# Step 2: Extract raster values at point locations
extracted <- terra::extract(forest_loss_1km, points_vect)

# Step 3: Combine extracted values with original sf
# `extracted` has ID + raster value, match back by row
points_sf$raster_value <- extracted[[2]]  # assuming it's the 2nd column


ggplot(points_sf, aes(x = A2, y = raster_value)) +
  geom_jitter(width = 0.2, height = 0, alpha = 0.5, color = "darkgreen") +
  geom_smooth(method = "lm", se = TRUE, color = "red", linewidth = 1) +
  labs(
    title = "Relationship Between Drought Index (A2) and Forest Loss",
    x = "Drought Index (A2: 1 = high drought, 5 = no drought)",
    y = "Forest Loss within 1km^2 Raster Cell (%)"
  ) +
  theme_minimal()

Code
ggsave("figures/forest_loss_perceived_drought.png", width=9, height=5, dpi="print")




ggplot(points_sf, aes(x = A2, y = dead_share_of_forest_10000, col=fl_por_10)) +
  geom_jitter(width = 0.2, height = 0, alpha = 0.5) +
  geom_smooth(method = "lm", se = TRUE, color = "red", linewidth = 1) +
  labs(
    title = "Relationship Between Drought Index (A2) and Forest Loss around Place of Residence",
    x = "Drought Index (A2: 1 = high drought, 5 = no drought)",
    y = "Forest Loss within 10km radius (%)"
  ) +
  theme_minimal()

Code
ggplot(points_sf, aes(x = A2, y = share_forest_10000, col=fl_por_10)) +
  geom_jitter(width = 0.2, height = 0, alpha = 0.5) +
  geom_smooth(method = "lm", se = TRUE, color = "red", linewidth = 1) +
  labs(
    title = "Relationship Between Drought Index (A2) and Forest Share around Place of Residence",
    x = "Drought Index (A2: 1 = high drought, 5 = no drought)",
    y = "Forest Share within 10km radius (%)"
  ) +
  theme_minimal()

Code
points_sf$drought_cat <- cut(
  points_sf$A2,
  breaks = c(0, 2, 3, 5),
  labels = c("High", "Medium", "Low"),
  right = TRUE,
  include.lowest = TRUE
)

ggplot(points_sf, aes(x = drought_cat, y = raster_value)) +
  geom_boxplot(fill = "lightblue", outlier.shape = NA) +
  geom_jitter(width = 0.2, alpha = 0.4, color = "darkgreen") +
  labs(
    title = "Forest Loss by Drought Severity Category",
    x = "Drought Severity (A2 grouped)",
    y = "Forest Loss within 1 km² Raster Cell (%)"
  ) +
  theme_minimal()

Code
points_sf <- points_sf %>% mutate(drought_agg = A2 + A3)

points_sf$drought_agg_cat <- cut(
  points_sf$drought_agg,
  breaks = c(0, 4, 7, 10),
  labels = c("High", "Medium", "Low"),
  right = TRUE,
  include.lowest = TRUE
)

points_sf <- points_sf %>% mutate(drought_agg = A2 + A3)


ggplot(points_sf, aes(x = drought_agg_cat, y = raster_value)) +
  geom_boxplot(fill = "lightblue", outlier.shape = NA) +
  geom_jitter(width = 0.2, alpha = 0.4, color = "darkgreen") +
  labs(
    title = "Forest Loss by Drought Severity Category",
    x = "Drought Severity (aggregated A2 and A3)",
    y = "Forest Loss within 1 km² Raster Cell (%)"
  ) +
  theme_minimal()

Code
ggplot(points_sf, aes(x = drought_agg, y = raster_value)) +
  geom_jitter(width = 0.2, height = 0, alpha = 0.5, color = "darkgreen") +
  geom_smooth(method = "lm", se = TRUE, color = "red", linewidth = 1) +
  labs(
    title = "Relationship Between Drought Index and Forest Loss",
    x = "Drought Index (2 = high drought, 10 = no drought)",
    y = "Forest Loss within 1km^2 Raster Cell (%)"
  ) +
  theme_minimal()

Check spatial correlation in drought index

Code
data_sf <- data_2025_complete

# Extract coordinates from the now-active geometry
coords <- sf::st_coordinates(data_sf)

# Variable of interest
y_raw <- data_sf$A2

# Keep only rows with finite y and valid coords
ok <- is.finite(y_raw) & is.finite(coords[,1]) & is.finite(coords[,2])
coords_ok <- coords[ok, , drop = FALSE]
y <- y_raw[ok]

# =============================================
# 1) Build distance-band neighbors (great-circle)
# =============================================
# We work in lon/lat with great-circle distances using longlat=TRUE.
# Define distance breaks in *kilometers* (tune to your scale).
breaks_km <- seq(0, 120, by = 2)  # 0-50, 50-100, ..., up to 1000 km

# Helper to compute Moran's I with permutation p-value for one band
band_moran <- function(d1, d2) {
  # Build neighbors for distances in [d1, d2)
  nb <- try(dnearneigh(coords_ok, d1 = d1, d2 = d2, longlat = TRUE), silent = TRUE)
  if (inherits(nb, "try-error")) return(NULL)
  if (length(nb) == 0) return(NULL)  # no neighbors at this band

  # Some bands may produce isolates; allow zero.policy
  lw <- nb2listw(nb, style = "W", zero.policy = TRUE)

  # Permutation test for Moran's I (more robust than asymptotic)
  mc <- moran.mc(y, lw, nsim = 999, zero.policy = TRUE, alternative = "two.sided")

  # Mean neighbor distance (km) in this band for a nice x-position
  dlist <- nbdists(nb, coords_ok, longlat = TRUE)
  mean_d <- mean(unlist(dlist))

  tibble(
    d_from = d1,
    d_to   = d2,
    d_mid  = ifelse(is.finite(mean_d), mean_d, (d1 + d2)/2),
    moranI = as.numeric(mc$statistic),
    p_val  = mc$p.value,
    n_links = sum(lengths(nb))  # total neighbor links used
  )
}

# Loop over bands and bind results (skip empty bands)
res_list <- lapply(seq_len(length(breaks_km) - 1), function(i) {
  band_moran(breaks_km[i], breaks_km[i + 1])
})
cor_df <- bind_rows(res_list) %>%
  filter(!is.na(moranI)) %>%
  mutate(sig = p_val < 0.05)

# =============================
# 2) Plot the distance correlogram
# =============================
ggplot(cor_df, aes(x = d_mid, y = moranI)) +
  geom_hline(yintercept = 0, linetype = "dashed", linewidth = 0.4, color = "grey40") +
  geom_line(linewidth = 0.6) +
  geom_point(aes(shape = sig), size = 2) +
  scale_shape_manual(values = c(`TRUE` = 16, `FALSE` = 1),
                     labels = c(`TRUE` = "p < 0.05", `FALSE` = "ns")) +
  labs(
    title = "Distance correlogram for Perceived Drought (A2)",
    subtitle = "Moran's I across distance bands; filled points indicate p < 0.05",
    x = "Distance (km, band mid-point)",
    y = "Moran's I"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.title = element_blank())

Code
#### do plot for dead forest share #####
data_sf <- sf::st_set_geometry(data_2025_complete, "geometry_depart")


# Extract coordinates from the now-active geometry
coords <- sf::st_coordinates(data_sf)


# Variable of interest
y_raw <- data_sf$forest_loss_visit_1km

# Keep only rows with finite y and valid coords
ok <- is.finite(y_raw) & is.finite(coords[,1]) & is.finite(coords[,2])
coords_ok <- coords[ok, , drop = FALSE]
y <- y_raw[ok]

# =============================================
# 1) Build distance-band neighbors (great-circle)
# =============================================
# We work in lon/lat with great-circle distances using longlat=TRUE.
# Define distance breaks in *kilometers* (tune to your scale).
breaks_km <- seq(0, 120, by = 5)  # 0-50, 50-100, ..., up to 1000 km

# Helper to compute Moran's I with permutation p-value for one band
band_moran <- function(d1, d2) {
  # Build neighbors for distances in [d1, d2)
  nb <- try(dnearneigh(coords_ok, d1 = d1, d2 = d2, longlat = TRUE), silent = TRUE)
  if (inherits(nb, "try-error")) return(NULL)
  if (length(nb) == 0) return(NULL)  # no neighbors at this band

  # Some bands may produce isolates; allow zero.policy
  lw <- nb2listw(nb, style = "W", zero.policy = TRUE)

  # Permutation test for Moran's I (more robust than asymptotic)
  mc <- moran.mc(y, lw, nsim = 999, zero.policy = TRUE, alternative = "two.sided")

  # Mean neighbor distance (km) in this band for a nice x-position
  dlist <- nbdists(nb, coords_ok, longlat = TRUE)
  mean_d <- mean(unlist(dlist))

  tibble(
    d_from = d1,
    d_to   = d2,
    d_mid  = ifelse(is.finite(mean_d), mean_d, (d1 + d2)/2),
    moranI = as.numeric(mc$statistic),
    p_val  = mc$p.value,
    n_links = sum(lengths(nb))  # total neighbor links used
  )
}

# Loop over bands and bind results (skip empty bands)
res_list <- lapply(seq_len(length(breaks_km) - 1), function(i) {
  band_moran(breaks_km[i], breaks_km[i + 1])
})
cor_df <- bind_rows(res_list) %>%
  filter(!is.na(moranI)) %>%
  mutate(sig = p_val < 0.05)

# =============================
# 2) Plot the distance correlogram
# =============================
ggplot(cor_df, aes(x = d_mid, y = moranI)) +
  geom_hline(yintercept = 0, linetype = "dashed", linewidth = 0.4, color = "grey40") +
  geom_line(linewidth = 0.6) +
  geom_point(aes(shape = sig), size = 2) +
  scale_shape_manual(values = c(`TRUE` = 16, `FALSE` = 1),
                     labels = c(`TRUE` = "p < 0.05", `FALSE` = "ns")) +
  labs(
    title = "Distance correlogram for dead forest share in forest \nusing place of residence",
    subtitle = "Moran's I across distance bands; filled points indicate p < 0.05",
    x = "Distance (km, band mid-point)",
    y = "Moran's I"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.title = element_blank())

Code
#### do plot for forest type #####
data_sf <- data_2025_complete


# Extract coordinates from the now-active geometry
coords <- sf::st_coordinates(data_sf)

# Variable of interest
y_raw <- data_sf$Q26

# Keep only rows with finite y and valid coords
ok <- is.finite(y_raw) & is.finite(coords[,1]) & is.finite(coords[,2])
coords_ok <- coords[ok, , drop = FALSE]
y <- y_raw[ok]

# =============================================
# 1) Build distance-band neighbors (great-circle)
# =============================================
# We work in lon/lat with great-circle distances using longlat=TRUE.
# Define distance breaks in *kilometers* (tune to your scale).
breaks_km <- seq(0, 150, by = 5)  # 0-50, 50-100, ..., up to 1000 km

# Helper to compute Moran's I with permutation p-value for one band
band_moran <- function(d1, d2) {
  # Build neighbors for distances in [d1, d2)
  nb <- try(dnearneigh(coords_ok, d1 = d1, d2 = d2, longlat = TRUE), silent = TRUE)
  if (inherits(nb, "try-error")) return(NULL)
  if (length(nb) == 0) return(NULL)  # no neighbors at this band

  # Some bands may produce isolates; allow zero.policy
  lw <- nb2listw(nb, style = "W", zero.policy = TRUE)

  # Permutation test for Moran's I (more robust than asymptotic)
  mc <- moran.mc(y, lw, nsim = 999, zero.policy = TRUE, alternative = "two.sided")

  # Mean neighbor distance (km) in this band for a nice x-position
  dlist <- nbdists(nb, coords_ok, longlat = TRUE)
  mean_d <- mean(unlist(dlist))

  tibble(
    d_from = d1,
    d_to   = d2,
    d_mid  = ifelse(is.finite(mean_d), mean_d, (d1 + d2)/2),
    moranI = as.numeric(mc$statistic),
    p_val  = mc$p.value,
    n_links = sum(lengths(nb))  # total neighbor links used
  )
}

# Loop over bands and bind results (skip empty bands)
res_list <- lapply(seq_len(length(breaks_km) - 1), function(i) {
  band_moran(breaks_km[i], breaks_km[i + 1])
})
cor_df <- bind_rows(res_list) %>%
  filter(!is.na(moranI)) %>%
  mutate(sig = p_val < 0.05)

# =============================
# 2) Plot the distance correlogram
# =============================
ggplot(cor_df, aes(x = d_mid, y = moranI)) +
  geom_hline(yintercept = 0, linetype = "dashed", linewidth = 0.4, color = "grey40") +
  geom_line(linewidth = 0.6) +
  geom_point(aes(shape = sig), size = 2) +
  scale_shape_manual(values = c(`TRUE` = 16, `FALSE` = 1),
                     labels = c(`TRUE` = "p < 0.05", `FALSE` = "ns")) +
  labs(
    title = "Distance correlogram for type of forest",
    subtitle = "Moran's I across distance bands; filled points indicate p < 0.05",
    x = "Distance (km, band mid-point)",
    y = "Moran's I"
  ) +
  theme_minimal(base_size = 12) +
  theme(legend.title = element_blank())

Visits stats forest loss

Code
data_2025_complete %>%
  filter(!is.na(fl_por_10)) %>% ggplot() + geom_boxplot(aes(x=as.factor(fl_por_10), y=for_dis, fill=as.factor(fl_por_10))) +
  scale_fill_manual(values=c("blue", "grey70", "red")) + labs(fill="Drought category", x="", y="Forest travel distance reported (cat.)", title="2025")

Code
data_2025_complete %>%
  filter(!is.na(fl_por_10)) %>% ggplot() + geom_boxplot(aes(x=as.factor(fl_por_10), y=dist_for_depart/1000, fill=as.factor(fl_por_10)), outliers = FALSE) +
  scale_fill_manual(values=c("blue", "grey70", "red")) + labs(fill="Drought category", x="", y="Forest travel distance computed (km)", title="2025")

Code
data_2017_complete %>%
  filter(!is.na(fl_por_10)) %>% ggplot() + geom_boxplot(aes(x=as.factor(fl_por_10), y=dist_for_depart/1000, fill=as.factor(fl_por_10)), outliers = FALSE) +
  scale_fill_manual(values=c("steelblue", "grey75", "indianred")) + labs(fill="Drought category", x="", y="Forest travel distance computed (km)", title="2017")

Code
data_2025_complete %>%
  filter(!is.na(fl_por_10)) %>% ggplot() + geom_boxplot(aes(x=as.factor(fl_por_10), y=forest_visits, fill=as.factor(fl_por_10)), outliers = FALSE) +
  scale_fill_manual(values=c("blue", "grey70", "red")) + labs(fill="Drought category", x="", y="Forest visits", title="2025")

Code
data_2017_complete %>%
  filter(!is.na(fl_por_10)) %>% ggplot() + geom_boxplot(aes(x=as.factor(fl_por_10), y=forest_visits, fill=as.factor(fl_por_10)), outliers = FALSE) +
  scale_fill_manual(values=c("steelblue", "grey75", "indianred")) + labs(fill="Drought category", x="", y="Forest visits", title="2017")

Check land cover

Code
points_vect <- vect(points_sf)

# Step 2: Extract raster values at point locations
extracted <- terra::extract(land_cover, points_vect)

# Step 3: Combine extracted values with original sf
# `extracted` has ID + raster value, match back by row
points_sf$land_cover <- extracted[[2]]  # assuming it's the 2nd column

table(points_sf$land_cover, dnn="Land cover of marked forest location")
Land cover of marked forest location
                   NoData           Artificial Land                 Open Soil 
                        0                       182                         1 
 High Seasonal Vegetation High Perennial Vegetation   Low Seasonal Vegetation 
                      982                       675                       116 
 Low Perennial Vegetation                     Water 
                      246                        17 
Code
# Check land cover for place of residence/departure point

points_custom_geom <- st_set_geometry(points_sf, points_sf$geometry_proj4)

# Convert to SpatVector
points_vect2 <- vect(points_custom_geom)

extracted_custom <- terra::extract(land_cover, points_vect2)

points_sf$land_cover_depart <- extracted_custom[[2]]  # assuming it's the 2nd column

table(points_sf$land_cover_depart, dnn="Land cover of departure point")
Land cover of departure point
                   NoData           Artificial Land                 Open Soil 
                        0                      1313                         2 
 High Seasonal Vegetation High Perennial Vegetation   Low Seasonal Vegetation 
                      337                       155                       164 
 Low Perennial Vegetation                     Water 
                      256                        29 
Code
check_points <- points_sf %>% filter(land_cover == "Artificial Land")


check_points <- st_transform(check_points, crs = 3035) 

buffers <- terra::buffer(vect(check_points), width = 100)  # use terra::buffer for SpatVector

# 2. Extract raster values from land_cover in these buffers
# `cells = TRUE` gets the cell IDs; `touches = TRUE` includes intersecting cells
buffer_extract <- terra::extract(land_cover, buffers, touches = TRUE)

# 3. Join point IDs from check_points to the extracted buffer values
# The 'ID' column in buffer_extract refers to row numbers of check_points
buffer_extract <- left_join(buffer_extract, check_points %>% mutate(ID = row_number()), by = "ID")

# 4. For each point, check if at least one neighboring value is NOT "Artificial Land"
buffer_summary <- buffer_extract %>%
  group_by(ID) %>%
  summarise(any_natural = any(category != "Artificial Land", na.rm = TRUE))

# 5. Join back to flagged check_points
check_points <- check_points %>%
  mutate(ID = row_number()) %>%
  left_join(buffer_summary, by = "ID")

table(check_points$any_natural, dnn="Natural areas in surrounding for weird patterns")
Natural areas in surrounding for weird patterns
FALSE  TRUE 
   28   154 
Code
check_points <- st_transform(check_points, crs = 4326)  # Ensure CRS is set for leaflet

check_points <- check_points %>% filter(any_natural == "FALSE")


leaflet(check_points) %>%
  addProviderTiles("OpenStreetMap") %>%
  addCircleMarkers(radius = 5)

Matching

Code
source("scripts/matching.R")

love.plot(
  m.out_base,
  stats     = "mean.diffs",
  abs       = TRUE,
  var.order = "unadjusted",
  line      = TRUE,
  thresholds = c(m = .1),   # optional threshold line at |SMD| = 0.1
  title = "Base Matching all equal"
)

Code
love.plot(
  m.out_exact,
  stats     = "mean.diffs",
  abs       = TRUE,
  var.order = "unadjusted",
  line      = TRUE,
  thresholds = c(m = .1),   # optional threshold line at |SMD| = 0.1
  title = "Exact Matching Bundesland"
)

Code
love.plot(
  m.out_mah,
  stats     = "mean.diffs",
  abs       = TRUE,
  var.order = "unadjusted",
  line      = TRUE,
  thresholds = c(m = .1),   # optional threshold line at |SMD| = 0.1
  title = "Mahalanobis Matching Lat Lon"
)

Code
love.plot(
  m.out_mah_exact,
  stats     = "mean.diffs",
  abs       = TRUE,
  var.order = "unadjusted",
  line      = TRUE,
  thresholds = c(m = .1),   # optional threshold line at |SMD| = 0.1
  title = "Mahalanobis + Exact Matching"
)

Code
b <- bal.tab(m.out_exact_county, un = TRUE)

# drop all rows whose name starts with "NAME_2"
b$Balance <- b$Balance[!grepl("^NAME_2", rownames(b$Balance)), ]

love.plot(
    b,
    stats     = "mean.diffs",
    abs       = TRUE,
    var.order = "unadjusted",
    line      = TRUE,
    thresholds = c(m = .1),   # optional threshold line at |SMD| = 0.1
    title = "Exact Matching Landkreis"
)

Code
ggplot() +
  geom_density(data = pairs_sf, aes(x = as.numeric(dist)/1000, fill = "Exact Bundesland"), alpha = 0.5) +
  geom_density(data = pairs_sf_base, aes(x = as.numeric(dist)/1000, fill = "Baseline"), alpha = 0.5) +
  geom_density(data = pairs_sf_mah_exact,aes(x = as.numeric(dist)/1000, fill = "Mahalanobis + exact"),alpha = 0.5) +
  geom_density(data = pairs_sf_county,aes(x = as.numeric(dist)/1000, fill = "Exact county"),alpha = 0.5) +
  scale_fill_manual(
    name   = "Matching method",       # legend title
    values = c(
      "Exact Bundesland"            = "steelblue",
      "Exact county"                = "darkorange",
      "Baseline"            = "grey",
      "Mahalanobis + exact" = "darkred"
    )
  ) +
  xlab("Distance between matched pairs (km)") +
  theme_minimal()

Code
ggplot() +
  geom_sf(data = germany_fed, alpha = 0.3) +
  geom_segment(
    data = test_seg,
    aes(x = x1, y = y1, xend = x2, yend = y2, colour = factor(subclass)),
    linewidth = 0.4,
    alpha = 0.7
  ) +
  geom_sf(
    data = test,
    aes(geometry = geometry_depart.x),
    colour = "darkred",
    size = 1.5
  ) +
  geom_sf(
    data = test,
    aes(geometry = geometry_depart.y),
    colour = "blue",
    size = 1.5
  ) +
  labs(col="Match_ID") +
  theme_minimal()

Code
patchwork::wrap_plots(c(age_pl, lon_pl, lat_pl), ncol = 1)

Code
patchwork::wrap_plots(cat_plots[cat_vars], ncol = 3)

Code
spat_plot

Code
cats_panel_treat

Mxl base model matched data

Code
ggplot(filter(ci_data_match, Group == "match_base"), 
       aes(x = factor(Coefficient, levels <- c("beta_height", "beta_deadwood_med", "beta_deadwood_high", "beta_age_two", "beta_age_multi", 
                                               "beta_mono_con", "beta_two_con", "beta_two_broad", "beta_two_mix", 
                                               "beta_three_mix", "beta_four_mix", "beta_infrastr2", 
                                               "beta_infrastr3", "beta_infrastr4", "beta_ASC_sq", "beta_dist")), y = Mean, color = Model)) +
  geom_point(size = 3, position = position_dodge(width = 0.6)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.2, position = position_dodge(width = 0.6)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "WTT Estimates with 90% Confidence Intervals",
    x = "Coefficient",
    y = "WTT Estimate (km)",
    color = "Model"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) 

Code
ggplot(ci_data_match,
       aes(x = Model, y = Mean, color = Model)) +
  
  geom_point(size = 3, position = position_dodge(width = 0.5)) +
  geom_errorbar(aes(ymin = Lower_CI, ymax = Upper_CI),
                width = 0.15,
                position = position_dodge(width = 0.5)) +
  facet_wrap(~ Coefficient, scales = "free_y") +
  
  labs(
    title = "WTT Estimates with 90% Confidence Intervals",
    x = "",
    y = "WTT Estimate (km)",
    color = "Model"
  ) +
  
  theme_minimal() 

Code
ggplot(did_df_match, aes(x = term, y = did, color = sig)) +
  geom_hline(yintercept = 0, linewidth = 0.4, linetype = "dashed", color = "grey40") +
  geom_pointrange(aes(ymin = ci_lo, ymax = ci_hi), linewidth = 0.7) +
  coord_flip() +
  scale_color_manual(values = c("Significant" = "red", "Not significant" = "black")) +
  labs(
    title = "Difference-in-differences: (High − Low) of (2025 − 2017)",
    subtitle = "Points and 90% robust CIs; red = p < 0.05",
    x = NULL,
    y = "Difference-in-differences",
    color = "Significance at 5% level"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.minor = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_text(angle = 0, hjust = 0.5),
    legend.position = "bottom"
  ) +
  scale_x_discrete(labels = function(x) sub("^beta_", "", x)) 

DiD Model matched data

Code
stargazer(mxl_match_did_out, 
          type = "html", 
          title = "Mixed Logit Model Output (2025) WTP Space DiD Matching",
          column.labels = "DiD Matching")
Mixed Logit Model Output (2025) WTP Space DiD Matching
Estimate s.e. t.rat.(0) Rob.s.e. Rob.t.rat.(0)
beta_mono_con 0.614 1.848 0.332 2.231 0.275
beta_two_con -4.141 2.266 -1.828 2.636 -1.571
beta_two_broad 5.416 2.137 2.535 2.169 2.497
beta_two_mix 5.383 1.381 3.898 1.412 3.813
beta_three_mix 7.531 1.407 5.354 1.655 4.551
beta_four_mix 15.959 1.973 8.088 2.425 6.581
beta_age_multi 3.831 1.361 2.815 1.633 2.345
beta_age_two -1.410 1.450 -0.973 1.660 -0.850
beta_deadwood_high 4.601 1.112 4.137 1.203 3.825
beta_deadwood_med 0.929 1.132 0.821 1.343 0.692
beta_height 1.383 0.123 11.260 0.176 7.867
beta_infrastr2 2.109 1.375 1.534 1.542 1.367
beta_infrastr3 13.654 1.659 8.232 2.532 5.392
beta_infrastr4 16.254 1.571 10.343 2.326 6.987
beta_ASC_sq 60.125 2.062 29.153 3.267 18.405
beta_dist -3.135 0.039 -79.765 0.069 -45.430
sig_mono_con 4.251 2.118 2.007 3.045 1.396
sig_two_con -8.179 1.799 -4.546 2.509 -3.260
sig_two_broad -4.870 3.939 -1.236 8.441 -0.577
sig_two_mix 0.723 0.913 0.792 1.021 0.708
sig_three_mix 8.987 1.063 8.456 1.438 6.250
sig_four_mix 14.652 0.964 15.200 1.111 13.182
sig_age_multi -0.594 1.268 -0.468 2.062 -0.288
sig_age_two -5.148 1.242 -4.145 1.762 -2.922
sig_deadwood_high 1.160 1.282 0.905 2.197 0.528
sig_deadwood_med 0.953 1.137 0.838 1.749 0.545
sig_height 0.664 0.059 11.169 0.086 7.739
sig_infrastr2 2.687 1.487 1.806 2.300 1.168
sig_infrastr3 6.128 1.272 4.817 2.007 3.054
sig_infrastr4 12.431 0.979 12.694 1.574 7.898
sig_ASC_sq 59.281 1.523 38.920 2.241 26.457
sig_dist 0.940 0.044 21.573 0.078 12.092
d_mono_con_2025 -3.743 2.841 -1.318 3.104 -1.206
d_mono_con_high 9.628 4.363 2.207 5.109 1.885
d_mono_con_DiD -4.668 6.040 -0.773 6.631 -0.704
d_two_con_2025 5.967 3.054 1.953 3.299 1.809
d_two_con_high 4.829 5.107 0.946 5.867 0.823
d_two_con_DiD -8.606 6.975 -1.234 7.733 -1.113
d_two_broad_2025 4.038 3.357 1.203 4.166 0.969
d_two_broad_high -7.343 5.935 -1.237 5.848 -1.256
d_two_broad_DiD 4.052 7.777 0.521 7.743 0.523
d_two_mix_2025 2.918 2.081 1.402 2.421 1.205
d_two_mix_high 0.430 3.566 0.121 3.856 0.112
d_two_mix_DiD -3.538 4.845 -0.730 5.333 -0.663
d_three_mix_2025 4.682 2.192 2.136 2.751 1.702
d_three_mix_high 2.965 3.987 0.744 5.710 0.519
d_three_mix_DiD -8.048 5.181 -1.553 6.752 -1.192
d_four_mix_2025 -1.144 2.972 -0.385 3.906 -0.293
d_four_mix_high 9.831 4.917 1.999 5.949 1.653
d_four_mix_DiD -15.289 6.472 -2.362 7.413 -2.062
d_age_multi_2025 0.671 2.020 0.332 2.606 0.257
d_age_multi_high 1.433 3.312 0.433 4.908 0.292
d_age_multi_DiD -1.164 4.619 -0.252 6.120 -0.190
d_age_two_2025 2.463 2.176 1.132 2.800 0.880
d_age_two_high -1.993 3.587 -0.556 4.577 -0.435
d_age_two_DiD 3.260 5.022 0.649 6.042 0.540
d_deadwood_high_2025 -0.475 1.599 -0.297 1.736 -0.274
d_deadwood_high_high -5.043 2.581 -1.954 3.064 -1.646
d_deadwood_high_DiD 6.403 3.577 1.790 3.959 1.617
d_deadwood_med_2025 2.732 1.660 1.646 1.886 1.448
d_deadwood_med_high -3.612 2.598 -1.391 3.026 -1.194
d_deadwood_med_DiD 4.965 3.584 1.385 3.960 1.254
d_height_2025 -0.499 0.179 -2.793 0.239 -2.092
d_height_high 0.060 0.252 0.238 0.334 0.180
d_height_DiD -0.240 0.365 -0.659 0.407 -0.590
d_infrastr2_2025 4.322 2.071 2.087 2.352 1.837
d_infrastr2_high 0.414 3.229 0.128 3.456 0.120
d_infrastr2_DiD -6.201 4.687 -1.323 5.285 -1.173
d_infrastr3_2025 -3.945 2.420 -1.630 3.522 -1.120
d_infrastr3_high 2.436 3.667 0.664 4.352 0.560
d_infrastr3_DiD -0.263 5.253 -0.050 6.557 -0.040
d_infrastr4_2025 1.009 2.415 0.418 3.301 0.306
d_infrastr4_high 0.693 3.709 0.187 5.163 0.134
d_infrastr4_DiD -4.751 5.196 -0.914 7.094 -0.670
d_ASC_sq_2025 1.997 4.132 0.483 6.489 0.308
d_ASC_sq_high 3.141 3.958 0.794 5.345 0.588
d_ASC_sq_DiD -4.730 8.058 -0.587 10.003 -0.473
Code
source("scripts/plot_did_coefficients.R")
Successfully loaded C:/Users/nc71qaxa/Nextcloud2/ICP_Forest_Share/#
  Drought R/models/mxl/pooled/MXL wtp did matching 10km
  thirds_model.rds
Successfully loaded C:/Users/nc71qaxa/Nextcloud2/ICP_Forest_Share/#
  Drought R/models/clogit/Clogit DID 10 km thirds_model.rds
Successfully loaded C:/Users/nc71qaxa/Nextcloud2/ICP_Forest_Share/#
  Drought R/models/clogit/CLOGIT_Exploded_DiD 10km thirds_model.rds
Successfully loaded C:/Users/nc71qaxa/Nextcloud2/ICP_Forest_Share/#
  Drought R/models/clogit/Clogit DID last forest thirds_model.rds
Successfully loaded C:/Users/nc71qaxa/Nextcloud2/ICP_Forest_Share/#
  Drought R/models/clogit/CLOGIT_Exploded_DiD last forest
  thirds_model.rds
Successfully loaded C:/Users/nc71qaxa/Nextcloud2/ICP_Forest_Share/#
  Drought R/models/mxl/pooled/MXL wtp did matching 10km
  thirds_model.rds
Successfully loaded C:/Users/nc71qaxa/Nextcloud2/ICP_Forest_Share/#
  Drought R/models/mxl/pooled/MXL wtp did matching last forest
  thirds_model.rds
Code
ggplot(did_df, aes(x = reorder(param, estimate), y = estimate)) +
  geom_point(size = 3) +
  geom_errorbar(aes(ymin = lower, ymax = upper), width = 0.2) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  coord_flip() +
  theme_minimal(base_size = 14) +
  labs(
    x = "DiD parameter",
    y = "Coefficient estimate",
    title = "Difference-in-Differences Coefficients \nwith Robust 90% CI Matched MXL",
    color = "Attribute group"
  )

Code
ggplot(all_df, aes(x = group, y = estimate, color = effect)) +
  geom_point(size = 3, position = pd) +
  geom_errorbar(aes(ymin = lower, ymax = upper), width = 0.2, position = pd) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  theme_minimal(base_size = 14) +
  labs(
    x = "DiD parameter",
    y = "Coefficient estimate",
    title = "Difference-in-Differences Coefficients \nwith Robust 90% CI",
    color = "Interaction effect"
  ) +
  coord_flip() 

Code
# Compare clogit and exploded logit 
ggplot(did_all, aes(x = clean_param, y = estimate, color = model)) +
  geom_point(position = position_dodge(width = 0.6), size = 3) +
  geom_errorbar(aes(ymin = lower, ymax = upper),
                position = position_dodge(width = 0.6),
                width = 0.2) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  coord_flip() +
  theme_minimal(base_size = 14) +
  labs(
    x = "DiD parameter",
    y = "Coefficient estimate",
    title = "Comparison of DiD Coefficients Across \nClogit Models (90% CI) 10 km Not matched",
    color = "Model"
  )

Code
ggplot(did_all_lv, aes(x = clean_param, y = estimate, color = model)) +
  geom_point(position = position_dodge(width = 0.6), size = 3) +
  geom_errorbar(aes(ymin = lower, ymax = upper),
                position = position_dodge(width = 0.6),
                width = 0.2) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  coord_flip() +
  theme_minimal(base_size = 14) +
  labs(
    x = "DiD parameter",
    y = "Coefficient estimate",
    title = "Comparison of DiD Coefficients Across \nClogit Models (90% CI) last forest Not Matched",
    color = "Model"
  )

Code
ggplot(did_all_mxl, aes(x = clean_param, y = estimate, color = model)) +
  geom_point(position = position_dodge(width = 0.6), size = 3) +
  geom_errorbar(aes(ymin = lower, ymax = upper),
                position = position_dodge(width = 0.6),
                width = 0.2) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  coord_flip() +
  theme_minimal(base_size = 14) +
  labs(
    x = "DiD parameter",
    y = "Coefficient estimate",
    title = "Comparison of DiD Coefficients Across \nMXL Models (90% CI) matched data",
    color = "Model"
  )

Behavioural changes

Code
source("scripts/behavioural_regressions.R")

texreg::htmlreg(lm(forest_visits ~ Did + high + year2025 + age  + female + uni_degree + log(dist_for_depart), data=full_data), stars = c(0.01, 0.05, 0.1), caption = "Regression results for forest visits", single.row = TRUE)
Regression results for forest visits
  Model 1
(Intercept) 69.05 (6.89)***
Did 2.11 (4.27)
high 2.11 (3.53)
year2025 -6.94 (3.02)**
age 0.12 (0.07)*
female 2.15 (1.99)
uni_degree -1.79 (2.10)
log(dist_for_depart) -5.66 (0.52)***
R2 0.07
Adj. R2 0.06
Num. obs. 2188
***p < 0.01; **p < 0.05; *p < 0.1
Code
texreg::htmlreg(lm(log(dist_for_depart) ~ Did + high + year2025 + age  + female + uni_degree , data=full_data),
                stars = c(0.01, 0.05, 0.1), caption = "Regression results for travel distance to forest", single.row = TRUE)
Regression results for travel distance to forest
  Model 1
(Intercept) 10.39 (0.18)***
Did 0.49 (0.18)***
high -0.42 (0.15)***
year2025 -0.20 (0.13)
age -0.02 (0.00)***
female 0.07 (0.08)
uni_degree 0.64 (0.09)***
R2 0.06
Adj. R2 0.06
Num. obs. 2188
***p < 0.01; **p < 0.05; *p < 0.1