斯里兰卡生态系统服务价值量计算

news2024/11/24 6:38:19

斯里兰卡生态服务价值计算


一、引言

生态系统服务价值是指人类间接直接从生态系统各服务功能中获得的收益,对人类社会福祉起着极其重要的贡献。生态系统服务价值核算作为一项基础性研究工作,对生态安全格局的构建、生态补偿以及生态文明建设等研究有重要的参考价值,对促进人与自然和谐共生以及人类自己的可持续发展有重要意义(熊睿毅,2021)。

联合国生态评估组将生态系统服务分为四类:

  • 供给服务
    • 供给服务主要是提供人类生存生活所必须的物质资源,譬如食物、水资源、原材料等
  • 调节服务
    • 调节服务是指生态系统在发挥维持自我稳定和自我修复的特性时提供的服务,主要包括水文调节、气体调节、气候调节、净化环境等功能
  • 支持服务
    • 支持服务是指作为其他服务的基础,起到支持和维持作用的服务,譬如土壤保持、生物多样性保持和养分循环维持等
  • 文化服务
    • 文化服务是指为人类提供的满足人类文化兴趣和需求的服务,譬如灵感获取、宗教服务、精神价值、教育价值等,其最大的特点就是非消耗性,不受到消费而减少。

本文采用模拟市场法进行价值评估,细化方法为当量因子法,所谓当量因子法就是将研究区分为若干个生态系统,将某一生态系统的单位面积当量因子与对应生态系统面积相乘得到该生态系统的服务价值。国内主流的是谢高地在Costanza的研究基础上进行改良后的适用于中国陆地生态系统的单位面积价值当量因子动态评估模型,其单位面积生态系统服务价值当量表如下:

在这里插入图片描述

单位面积生态系统服务价值当量

生态系统服务价值量的计算公式如下:
E S V = ∑ m = 1 x A m ∑ n = 1 y E m n ESV=\sum_{m=1}^xA_m\sum_{n=1}^yE_{mn} ESV=m=1xAmn=1yEmn
其中, m m m为第 m m m类生态系统, n n n为第 n n n个服务功能, A m A_m Am为研究范围内第 m m m个生态系统的面积, E m n E_{mn} Emn则是该服务功能的标准单位价值。

标准单位 E S V ESV ESV当量因子的价值公式为:
V = 1 / 7 × P × Q V=1/7\times P\times Q V=1/7×P×Q
其中, P P P表示粮食均价, Q Q Q表示粮食单产。


二、数据源

土地覆盖数据来自于Esri公司的Sentinel-2 Land Cover Explorer产品,网址为:https://livingatlas.arcgis.com/landcoverexplorer/#mapCenter=-66.80083417615404%2C-9.321964396201427%2C11&mode=step&timeExtent=2017%2C2022&year=2022。该产品提供了哨兵二号获取的2017-2020年10m分辨率的全球土地覆盖类型数据,一共有九类,包括水系、森林、湿地、耕地、建筑用地、裸地、冰雪、云层、草甸。

行政区划数据来自于GADM官网,该数据集提供了全球所有国家及其下级行政区划的矢量边界和空间数据,网址为:https://gadm.org/index.html。值得注意的,这里的中国数据并没有台湾和九段线,不建议在这里下载精确的国家数据。

统计年鉴数据,包括主要农作物产量、单价,来自于国际粮农组织,官网为:https://www.fao.org/faostat/en/#data


三、数据处理

3.1 数据预处理

3.1.1 土地覆盖类型数据处理

在Esri上下载的土地覆盖类型数据,每一年都有两幅图像,如下图所示,我们需要做的就是将其拼接起来,并通过斯里兰卡矢量边界进行裁剪。

在这里插入图片描述

土地覆盖数据

其中,镶嵌至新栅格在工具箱中的位置如下:数据管理->栅格->栅格数据集->镶嵌至新栅格

裁剪在工具箱中的位置如下:数据管理->栅格->栅格处理->裁剪

新建一个个人地理数据库,并将下载的2017-2022年数据处理好后保存到该数据库。

在这里插入图片描述

工作数据库

裁剪完之后,数据分类值域会自动填充至[0,255],这并不是我们想要的,因此,通过栅格计算器工具处理掉不需要的值。

在这里插入图片描述

异常数据

栅格计算器工具位于空间分析工具->地图代数->栅格计算器,计算表达式为:Con("lc2021">11,0,"lc2021"),该条件语句将大于11的值映射至0,而小于11的保持原状。

3.1.2 产量、价格数据处理

我们读取数据,并进行简单的统计量查看。

import pandas as pd

path=r"Path"
yield_=pd.read_csv(path+r"\yield.csv")
pp_=pd.read_csv(path+r"\Producer Prices.csv")
yield_.head()

在这里插入图片描述

产量数据

需要用到的属性只有Item,Year,Unit,Value,为了保证数据的时效性,我们只使用2000年以后的数据。因此需要对原始数据做时间和属性上的筛选。

yield_=yield_[["Item","Year","Unit","Value"]]
yield_=yield_[yield_["Year"]>2000]

# 对于价格数据同理
pp_=pp_[["Item","Year","Value","Element"]]
pp_=pp_[pp_["Year"]>2000]

实际上,在这个数据里,产量已经没有问题了。我们只需要做一个简单的处理:

yield_.groupby("Item").mean()["Value"]/10 #转为千克

在这里插入图片描述

平均产量

便可拿到每种作物近二十年的平均产量(单位:千克/公顷)。


3.2 基于LSTM的简单时间序列数据扩充

从世界粮农组织获得Sri Lanka主要农作物产量和价格数据时,其中的主要作物Sorghum仅有2001-2006年的数据,而Millet只有2001-2005,2020-2021这样的间断数据。虽然说可以直接剔除这种过分缺失的数据,但这无疑会对生态因子的计算造成重大影响。为了尽可能保证数据的稳定,我们采用循环神经网络来对数据进行拟合扩充。

3.2.1 数据探查

在上一小节,我们读入了产量和价格数据。实际上,这个价格数据是有问题的。

pp_.tail(10)

在这里插入图片描述

产量数据

高粱数据最新只到2006年。

3.2.2 模型构建

在本小节,我们将比较传统一维CNN与RNN在结果上的异同。

一般做一维RNN时,可以指定一个时间窗口,比如用2006,2007,2008年的数据,推理2009年的数据,用2007,2008,2009年推理2010年。

我们现在要用之前处理好的pp_c数据中的玉米产量,来预测高粱产量。所以第一步就是将其转化为torch接受的格式。

别忘记导入模块:

import torch
import torch.nn as nn
from torch.nn import functional as F
x=pp_c[pp_c['Item']=="Maize (corn)"]['Value']
x=torch.FloatTensor(x)

之前写数据迭代器的时候,除了可以继承自torch.utils.data.DataLoader,也可以是任意的可迭代对象。这里我们可以简单的设置一个类:

# 设置迭代器
class MyDataSet(object):
    def __init__(self,seq,ws=6):
        # ws是滑动窗口大小
        self.ori=[i for i in seq[:ws]]
        self.label=[i for i in seq[ws:]]
        self.reset()
        self.ws=ws

    def set(self,dpi):
        # 添加数据
        self.x.append(dpi)
        
    def reset(self):
        # 初始化
        self.x=self.ori[:]
        
    def get(self,idx):
        return self.x[idx:idx+self.ws],self.label[idx]
    
    def __len__(self):
        return len(self.x)

在对数据按照时间窗口进行处理时,主要有两种方式,一种是用原始数据做预测,一种是用预测数据做预测。

假设 A = [ a 1 , a 2 , a 3 , a 4 , a 5 , a 6 ] A=[a1,a2,a3,a4,a5,a6] A=[a1,a2,a3,a4,a5,a6],时间窗口大小为3。

用原始数据做预测,那么输入值为: a 1 , a 2 , a 3 a1,a2,a3 a1,a2,a3,得到的结果将与 a 4 a4 a4做比较。下一轮输入为 a 2 , a 3 , a 4 a2,a3,a4 a2,a3,a4,得到的结果将与 a 5 a5 a5做比较。

而用预测的数据做预测,第一轮输入值为 a 1 , a 2 , a 3 a1,a2,a3 a1,a2,a3,得到的结果是 b 4 b4 b4,在与 a 4 a4 a4做比较后,下一轮的输入为 a 2 , a 3 , b 4 a2,a3,b4 a2,a3,b4,会出现如下情况:

输入数据为 b 4 , b 5 , b 6 b4,b5,b6 b4,b5,b6

ws=6 # 全局时间窗口
train_data=MyDataSet(x,ws)

网络的架构如下:

   
class Net3(nn.Module):
    def __init__(self,in_features=54,n_hidden1=128,n_hidden2=256,n_hidden3=512,out_features=7):
        super(Net3, self).__init__()
        self.flatten=nn.Flatten()
        self.hidden1=nn.Sequential(
            nn.Linear(in_features,n_hidden1,False),
           
            nn.ReLU()
        )
        self.hidden2=nn.Sequential(
            nn.Linear(n_hidden1,n_hidden2),

            nn.ReLU()
        )
        self.hidden3=nn.Sequential(
            nn.Linear(n_hidden2,n_hidden3),

            nn.ReLU()
        )
        self.out=nn.Sequential(nn.Linear(n_hidden3,out_features))

    def forward(self,x):
        x=self.flatten(x)
        x=self.hidden2(self.hidden1(x))
        x=self.hidden3(x)
        return self.out(x)



class CNN(nn.Module):
    def __init__(self, output_dim=1,ws=6):
        super(CNN, self).__init__()
        self.relu = nn.ReLU(inplace=True)
        self.conv1 = nn.Conv1d(ws, 64, 1)
        self.lr = nn.LeakyReLU(inplace=True)
        self.conv2 = nn.Conv1d(64, 128, 1)

        self.bn1, self.bn2 = nn.BatchNorm1d(64), nn.BatchNorm1d(128)
        self.bn3, self.bn4 = nn.BatchNorm1d(1024), nn.BatchNorm1d(128)
        self.flatten = nn.Flatten()
        self.lstm1 = nn.LSTM(128, 1024)
        self.lstm2 = nn.LSTM(1024, 256)
        self.lstm3=nn.LSTM(256,512)
        self.fc = nn.Linear(512, 512)
        self.fc4=nn.Linear(512,256)
        self.fc1 = nn.Linear(256, 64)
        self.fc3 = nn.Linear(64, output_dim)

    @staticmethod
    def reS(x):
        return x.reshape(-1, x.shape[-1], x.shape[-2])

    def forward(self, x):
        x = self.reS(x)
        x = self.conv1(x) 
        x = self.lr(x)

        x = self.conv2(x) 
        x = self.lr(x)

        x = self.flatten(x)

        # LSTM部分
        x, h = self.lstm1(x)
        x, h = self.lstm2(x)
        x,h=self.lstm3(x)
        x, _ = h

        x = self.fc(x.reshape(-1, ))
        x = self.relu(x)
        x = self.fc4(x)
        x = self.relu(x)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc3(x)

        return x

训练部分

def Train(model,train_data,seed=1):
    device="cuda" if torch.cuda.is_available() else "cpu"
    model=model.to(device)
    Mloss=100000
    path=r"YourPath\%s.pth"%seed
    # 设置损失函数,这里使用的是均方误差损失
    criterion = nn.MSELoss()
    # 设置优化函数和学习率lr
    optimizer=torch.optim.Adam(model.parameters(),lr=1e-5,betas=(0.9,0.99),
                               eps=1e-07,weight_decay=0)
    # 设置训练周期
    epochs =3000
    criterion=criterion.to(device)
    model.train()
    for epoch in range(epochs):
        total_loss=0

        for i in range(len(x)-ws):
            # 每次更新参数前都梯度归零和初始化
            seq,y_train=train_data.get(i) # 从我们的数据集中拿出数据
            seq,y_train=torch.FloatTensor(seq),torch.FloatTensor([y_train])
            seq=seq.unsqueeze(dim=0)
            seq,y_train=seq.to(device),y_train.to(device)

            optimizer.zero_grad()
            # 注意这里要对样本进行reshape,
            # 转换成conv1d的input size(batch size, channel, series length)
            y_pred = model(seq)
            loss = criterion(y_pred, y_train)
            loss.backward()
            train_data.set(y_pred.to("cpu").item()) # 再放入预测数据
            optimizer.step()
            total_loss+=loss

        train_data.reset()
        if total_loss.tolist()<Mloss:
            Mloss=total_loss.tolist()
            torch.save(model.state_dict(),path)
            print("Saving")
        print(f'Epoch: {epoch+1:2} Mean Loss: {total_loss.tolist()/len(train_data):10.8f}')
    return model
d=CNN(ws=ws)
Train(d,train_data,"Net1")

在这里插入图片描述

模型损失

平均损失在10点左右。

checkpoint=torch.load(r"YourPath\4.pth")
d.load_state_dict(checkpoint) # 加载最佳参数
d.to("cpu")

3.2.3 结果可视化

我们这里用到Pyechart进行可视化。

from pyecharts.charts import *
from pyecharts import options as opts
from pyecharts.globals import CurrentConfig
pre,ppre=[i.item() for i in x[:ws]],[]
# pre 是用原始数据做预测
# ppre 用预测数据做预测
for i in range(len(x)-ws+1):
    ppre.append(d(torch.FloatTensor(x[i:i+ws]).unsqueeze(dim=0)))
    pre.append(d(torch.FloatTensor(pre[-ws:]).unsqueeze(dim=0)).item())
l=Line()
l.add_xaxis([i for i in range(len(x))])
l.add_yaxis("Original Data",x.tolist())
l.add_yaxis("Pred Data(Using Raw Datas)",x[:ws].tolist()+[i.item() for i in ppre])
l.add_yaxis("Pred Data(Using Pred Datas)",pre)
l.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
l.set_global_opts(title_opts=opts.TitleOpts(title='LSTM CNN'))

l.render_notebook()

根据时间窗口的不同,可以得到不同的结果。

在这里插入图片描述

窗口大小为4

在这里插入图片描述

窗口大小为5

在这里插入图片描述

窗口大小为6

从结果上来看,在一定范围内,时间窗口越大,损失误差越小。

至于验证,我们可以选Rice做验证:

x=torch.FloatTensor(pp_c[pp_c['Item']=="Rice"]['Value'].tolist())
pre,ppre=[i.item() for i in x[:ws]],[]
for i in range(len(x)-ws+1):
    ppre.append(d(torch.FloatTensor(x[i:i+ws]).unsqueeze(dim=0)))
    pre.append(d(torch.FloatTensor(pre[-ws:]).unsqueeze(dim=0)).item())
l=Line()
l.add_xaxis([i for i in range(len(x))])
l.add_yaxis("Original Data",x.tolist())
l.add_yaxis("Pred Data(Using Raw Datas)",x[:ws].tolist()+[i.item() for i in ppre])
l.add_yaxis("Pred Data(Using Pred Datas)",pre)
l.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
l.set_global_opts(title_opts=opts.TitleOpts(title='LSTM CNN'))

l.render_notebook()

在这里插入图片描述

基于Rice数据的验证结果

可以发现,用预测做预测的结果,基本上不会差太多,那也就意味着,我们可以对高粱进行预测。不过在这之前,我们可以看看用原始数据做训练的结果:

在这里插入图片描述

采用原始数据作训练的结果

时间窗口一样为6,可以看到在黑线贴合的非常好,但是面对大量缺失的数据,精度就远不如用预测数据做预测的结果了。

此外,这是用CNN做的结果

在这里插入图片描述

CNN拟合结果

我们可以发现LSTM的波动要比CNN好,CNN后面死水一潭,应该是梯度消失导致的,前面信息没有了,后面信息又是自个构造的,这就导致了到后面变成了线性情况。

那么最后的最后,就是预测高粱产量了:

pre_data=pp_c[pp_c['Item']=='Sorghum']['Value'].tolist()
l=pre_data[:]
for i in range(len(x)-ws+1):
    l.append(d(torch.FloatTensor(l[-ws:]).unsqueeze(dim=0)).item())
L=Line()
L.add_xaxis([i for i in range(len(x))])
L.add_yaxis("Pred",l)
L.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
L.set_global_opts(title_opts=opts.TitleOpts(title='sorghum production forecasts')
                            
                             )

L.render_notebook()
l.to_csv("path")

在这里插入图片描述

高粱价格拟合曲线

将结果数据更新。

for i in range(1,len(x)-ws):
	pp_c=pp_c.append({"Unnamed: 0":91+i,"Year":2006+i,"Value":l[5+i],"Item":"Sorghum",'Unit':"卢比/kg"},ignore_index=True)

3.3 斯里兰卡总ESV计算

对于我们前面得到的数据,依据价值公式计算生态服务单位价值表。

y=pd.read_excel(path+r"\yield_final.xlsx")
p=pd.read_excel(path+r"\Price_Mean.xls")

s=0
for _ in y["Item"].unique():
    s+=y[y['Item']==_]['Value'].tolist()[0]*p[p['Item']==_]["Price"].tolist()[0]
s/=4*7

可以得到这样一个因子:

s:16111.103594750322

该因子表示每公顷的价值。接下来,我们读取生态系统服务价值表,该表根据本项目的类型做过修改。即:保留存在的类型,剔除不存在的类型,将森林因子记作针叶林、阔叶林、针阔混交林的平均值。

e=pd.read_excel(path+r"/Esv_table.xls")

在这里插入图片描述

改进标准价值当量
for i in e.columns:
    if e[i].dtype ==np.float64:
        e[i]=e[i]*16111 # 不保留小数部分了

于是,可以得到我们的最终结果表。

在这里插入图片描述

价值当量

将每年的土地覆盖属性表导出,接着将利用这些数据计算最终结果。

path=r"E:\Sri Lanka\attributeTable"

values=r"E:\Sri Lanka\ESV_Pro.csv"  # 这个就是上面那张表的导出

mapTable={
    1:"水系",
    2:"森林(针+针阔+阔叶)//3",
    4:"湿地",
    5:"耕地(旱地)",
    7:"城镇用地",
    8:"裸地",
    9:"冰川积雪",
    10:"云层",
    11:"草原"
}

from collections import defaultdict


AT=[]
tab=os.listdir(path)
tables=[i for i in tab if i.endswith("t.csv")]
# ['2017t.csv', '2018t.csv', '2019t.csv', '2020t.csv', '2021t.csv', '2022t.csv']
for i in range(len(tables)):
    newT=defaultdict(int)
    year=tables[i].split('.')[0]
    tb=pd.read_csv(os.path.join(path,tables[i]))
    for i in range(len(tb)):
        if (k:=mapTable[tb["Value"][i]]) in v["Unnamed: 0"].unique():
            _=tb['Count'][i]/100
            for n,g in enumerate(v.columns[2:].tolist(),2):
                  # 每一项都等于 每种类型的像元乘以该像元在该项之下的价值之和
                newT[g]+=_/1e10*v[v["Unnamed: 0"]==k].iloc[0,n]
    AT.append(newT)
d=pd.DataFrame(AT,index=["%s"%i for i in range(2017,2023)])

其结果如下:

在这里插入图片描述

分项ESV量表

其中,食物生产、原料生产、水资源供给属于供给服务,气体调节、气候调节、净化环境、水文调节属于调节服务,水土保持、养分循环、生物多样性属于支持服务,美学景观属于文化服务

newD=pd.DataFrame([],columns=["供给服务","调节服务","支持服务","文化服务"])
newD["供给服务"]=d.iloc[:,0]+d.iloc[:,1]+d.iloc[:,2]
x=d.iloc[:,3]
for i in range(4,7):
    x+=d.iloc[:,i]
newD["调节服务"]=x
x=d.iloc[:,7]
for i in range(8,10):
    x+=d.iloc[:,i]
newD['支持服务']=x
newD['文化服务']=d.iloc[:,-1]

在这里插入图片描述

大类ESV量表

剩下的工作就是绘制图表了。


3.4 斯里兰卡行政县ESV变化情况

在本部分中,我们将研究分析2017-2022年斯里兰卡各个行政县的ESV变化,并通过人为设置分级,对其总量进行量化。其计算公式如下:

值(单位:10亿/卢比)级别
0-3
3-6较低
6-9中等
9-12较高
>12

为了能够实现按照各个省份分级,需将原本的土地覆盖栅格数据按照县面多边形进行裁剪,创建独立的县单元栅格,方便我们进行处理。当然,如果只是想做简单的聚合,则不需要进行独立栅格的构建,直接使用分区统计工具即可。

斯里兰卡有二十五个行政县,如果一个个用手点的话,是不是有些麻烦了,批处理也不支持迭代处理要素,那么有没有什么更加便捷的自动化操作呢?一开始我想的是用脚本来做,但是看到ArcGIS里面有一个模型构建器。通过模型构建器,可以创建迭代工作流,进而实现我们的需求。

在这里插入图片描述

裁剪模型迭代器

对行政区矢量数据内的所有面要素进行迭代,并将其作为裁剪工具的输入面要素,即可实现端到端的一键式任务流。将拆分数据的工作空间设置为一个新的mdb文件,即可获得分割好的数据。

在这里插入图片描述

迭代结果

由于分割的栅格没有属性表,此时我们需要迭代对其构建属性表。同样,可以使用模型构建器来进行,亦或是通过属性->符号系统来构建属性表。再拿到属性表之后,我们的数据应该是这样的:

在这里插入图片描述

地图效果

颜色斑杂是因为每个独立区块使用的色彩分级不一样,但这并不是我们要关注的重点。下一步操作将会导出这些属性表,并进行可视化。同样使用模型构建器,可以导出属性表:

在这里插入图片描述

属性表导出迭代器

表转Excel位于转换工具->Excel->表转Excel。

表至表位于转换工具->转出至地理数据库->表至表。

该操作后,我们便可取到对应栅格数据的数据表。下一步的工作内容是对这些表格进行处理,计算ESV价值。

在这里插入图片描述

导出结果

实际上,这个属性表长这个样子:

在这里插入图片描述

属性表

需要关注的就是Value属性和Count属性,前者代表土地覆盖类型,我们通过一个映射函数将映射到实际含义上,后者表示像元个数,注意像元大小是10m by 10m,如果换算成公顷,需要除以100。

path=r"E:\Sri Lanka\SubDivision" # 文件路径
mapTable={
    1:"水系",
    2:"森林(针+针阔+阔叶)//3",
    4:"湿地",
    5:"耕地(旱地)",
    7:"城镇用地",
    8:"裸地",
    9:"冰川积雪",
    10:"云层",
    11:"草原"
} # 映射表

values=r"E:\Sri Lanka\ESV_Pro.csv" # 前面得到的最终因子价值
v=pd.read_csv(values)
v.drop(v.columns[0],axis=1,inplace=True)



def getValue(year):
    def f(tem):
        Sum=0
        for i in range(len(tem)):
            # 若映射存在
            if(k:=mapTable[tem['Value'][i]]) in v['Unnamed: 0'].unique():
                _=tem['Count'][i]/100 # 换算成公顷
                Sum+=v[v['Unnamed: 0']==k].iloc[0,1:].sum()*_ # 总价值=\sum c_i*v_i
        return Sum
    dicT=defaultdict(int)
    tabs=os.listdir(path+r"\%sTabs"%year)
    total_esv=0
    for i in tabs:
        tb=pd.read_excel(path+r"\%sTabs\\"%year+i)
        total_esv+=(k:=f(tb))
        dicT[i.split("_")[0]]=k/1e10
    return total_esv/1e10,dicT

为了验证该函数,我们可以尝试读取一下数据:

getValue(2017)[0] # 获取2017年全国总量
结果比对

从结果上,与前面未做分割的全国数据大致相等。由于按照多边形分割不可避免的会造成像元损失,因此该结果会小于整体的结果,误差在可接受范围内。

下一步,需要计算各个县每年的总量。

Stable=[getValue(i) for i in range(2017,2023)]
DataShow=pd.DataFrame([],columns=[str(i) for i in range(2017,2023)])
# 实际上,DF可以直接传入一个Dict,Key将作为Index,value将作为列值
for i in range(2017,2023):DataShow[str(i)]=Stable[i-2017][1]

在这里插入图片描述

各县市年总ESV量表

我们将这个结果表导出,下一步便是在ArcGIS中绘制地图。

通过属性表的连接操作,可以将导出的表添加到矢量图中,然后就是对其进行地图制作,这方面不再赘述。

在这里插入图片描述

制图结果

再进一步,我们将利用imageio模块绘制动态图。

import imageio
def create_gif(filelist,name,dur=1.5):
    IMG=[]
    for i in filelist:
        IMG.append(imageio.imread(i))
    return imageio.mimsave(name,IMG,'GIF',duration=dur)
path=[os.path.join(r"E:\Sri Lanka\Res\Img",i) for i in os.listdir(r"E:\Sri Lanka\Res\Img")]
create_gif(path,r"E:\Sri Lanka\Res\Img\res.gif")

在这里插入图片描述

各省ESV年变化情况

结果如上图所示。


四、结果展示

在这里插入图片描述

斯里兰卡生态系统服务价值变化表

在斯里兰卡生态系统服务中,调节服务占了较大的比重,而文化服务的价值量较低,这与斯里兰卡大量的森林植被、湿地草甸覆盖有关。总体的价值量呈现波动上升趋势,说明斯里兰卡在新型人地关系的构建与维护上成果斐然。

在这里插入图片描述

斯里兰卡2022ESV分项占比

在这里插入图片描述

各分项年变化情况

在这里插入图片描述

从各省结果来看,斯里兰卡的中部和东部具有较高的价值量,且随着时间变化,东部、中部地区总量呈现增加趋势,而MataraPuttalam两个省份则是刚好在分界线上呈现先下降后上升的结果。


五、参考文献

熊睿毅. 福建省生态系统服务价值动态评估及影响因子研究[D].武汉大学,2021.DOI:10.27379/d.cnki.gwhdu.2021.000700.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/913898.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】socket编程(一)

目录 预备知识 理解源ip地址和目的ip地址 认识端口号 理解"端口号"和"进程ID" 认识TCP和UDP协议 网络字节序 socket编程接口 socket常见API socket bind listen accept conncet sockaddr与sockaddr_in socket的使用(简易UDP网络程序的编…

17款奔驰S400升级原厂无钥匙进入系统,提升您的便利性

奔驰无钥匙进入功能&#xff0c;只要身上装着车钥匙进入车内&#xff0c;车辆就能感应到钥匙的存在&#xff0c;这时只需按下启动键就可启动车辆了 奔驰无钥匙进入功能主要有两大使用体验&#xff0c;首先就是要注意主驾驶位车门的有效检测距离不小于1.5m&#xff0c;其他门钥匙…

2022年09月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;课程冲突 小 A 修了 n 门课程, 第 i 门课程是从第 ai 天一直上到第 bi 天。 定义两门课程的冲突程度为 : 有几天是这两门课程都要上的。 例如 a11&#xff0c;b13&#xff0c;a22&#xff0c;b24 时, 这两门课的冲突程度为 2。 现在你需要求的是这 n 门课中冲…

vue 中 axios 的安装及使用

vue 中 axios 的安装及使用 1. axios 安装2. axios使用 1. axios 安装 首先&#xff0c;打开当前的项目终端&#xff0c;输入 npm install axios --save-dev验证是否安装成功&#xff0c;检查项目根目录下的 package.json,其中的 devDependencies 里面会多出一个axios及其版本…

【中国善网】资源对接(场地捐赠)公示

-----仰和百花心理咨询认领安利公益基金会捐赠场地 近日&#xff0c;经过中国善网与安利公益基金会的沟通与对接&#xff0c;仰和百花心理咨询获得免费认领安利公益基金会场地&#xff08;安利深圳体验馆&#xff09;8月22-25日为期4天的使用权&#xff0c;特此公示。为推动公…

(嵌入式c语言)类型修饰符

类型修饰符 对内存资源存储位置的限定 auto 默认的类型修饰符 修饰的变量可读可写 register 因为你内部寄存器比较少&#xff0c;使用此类型修饰符&#xff0c;会告诉编译器尽量把此数据放到寄存器。 CPU内部寄存器是编号来定义&#xff0c;无地址编号&#xff0c;所以r…

网络控价方法论

品牌为什么要做控价&#xff1f; 不做控价的品牌&#xff0c;会面对价值受损、经销商流失、口碑下降的局面&#xff0c;因为低价不是一家店铺的行为&#xff0c;会随着时间的推移&#xff0c;不断蔓延&#xff0c;当越来越多的店铺低价&#xff0c;则表示渠道越来越乱&#xf…

亚马逊或将更改付款期限?卖家如何有效应对?

据外媒报道&#xff0c;亚马逊将更改其付款期限&#xff0c;英国和欧洲的卖家必须等到商品交付一周后才能收到款项。这项变更将于9月1日至6日分阶段生效&#xff0c;目前亚马逊已经向欧洲和英国的卖家发出通知。 一、亚马逊付款期限调整有何影响&#xff1f; 据了解&#xff…

【Python原创设计】基于Python Flask的上海美食信息与可视化宣传网站项目-附下载方式以及往届优秀论文,原创项目其他均为抄袭

基于Python Flask的上海美食信息与可视化宣传网站&#xff08;获取方式访问文末官网&#xff09; 一、项目简介二、开发环境三、项目技术四、功能结构五、运行截图六、功能实现七、数据库设计八、源码获取 一、项目简介 随着大数据和人工智能技术的迅速发展&#xff0c;我们设…

【React基础全篇】

文章目录 一、关于 React二、脚手架2.1 create-react-app 脚手架的使用2.2 项目目录解析2.3 抽离配置文件2.4 webpack 二次封装2.4.1 集成 css 预处理器2.4.2 配置解析别名 2.5 setupProxy 代理 三、JSX3.1 jsx 语法详解3.2 React.createElement 四、组件定义4.1 类组件4.2 函数…

日常中msvcp140.dll丢失是什么原因,msvcp140.dll丢失4个解决方法

在计算机编程过程中&#xff0c;我们可能会遇到各种错误和问题。其中&#xff0c;丢失msvcp140.dll文件是一个常见的问题。msvcp140.dll是Microsoft Visual C 2015 Redistributable的一部分&#xff0c;它包含了运行许多应用程序所需的运行时库。当这个文件丢失时&#xff0c;可…

【Python原创设计】基于Python Flask的全国气象数据采集及可视化系统-附下载方式以及项目参考论文,原创项目其他均为抄袭

基于Python Flask的全国气象数据采集及可视化系统 一、项目简介二、项目技术三、项目功能四、运行截图五、分类说明六、实现代码七、数据库结构八、源码下载 一、项目简介 本项目是一个基于Web技术的实时气象数据可视化系统。通过爬取中国天气网的各个城市气象数据&#xff0c…

【Go语言】基于Socket编程的P2P通信程序示例

Go语言的Socket编程实现为开发者提供了一种高效且强大的方式来实现网络通信。通过Go语言的并发模型和内置的网络库&#xff0c;如net包&#xff0c;开发者可以轻松地创建基于套接字的通信应用。Go语言的goroutine和channel机制使并发处理变得简单&#xff0c;能够轻松处理多个连…

Address already in use: bind 如何解决端口号被占用

Address already in use: bind 程序报错&#xff0c;说明端口号已经被占用了。在不重启计算机的情况下&#xff0c;可通过如下方式解决 一&#xff1a; winR 快捷键 输入cmd指令打开黑框 二&#xff1a;输入指令 netstat -ano 查看端口号 三&#xff1a;根据端口号&#xff0c…

色差分量接口ESD静电保护推荐TVS二极管:DW03DLC-B-S和DW05R-E

YCbCr/YPbPr色差分量接口是S-Video端子的升级产品&#xff0c;支持1080P高清&#xff0c;由红、绿、蓝三种颜色的线组成&#xff0c;其中&#xff0c;蓝色和红色分别传输蓝色差信号&#xff08;Cb/Pb&#xff09;和红色差信号&#xff08;Cr/Pr&#xff09;&#xff0c;而绿色传…

【vue3+ts项目】配置husky+配置commitlint

上一篇文章中配置了eslint校验代码工具 【vue3ts项目】配置eslint校验代码工具&#xff0c;eslintprettierstylelint 1、配置husky 每次手动执行命令才能格式化代码&#xff0c;如果有人没有格式化就提交到远程仓库&#xff0c;这个规范就起不到作用了&#xff0c;所有需要强…

【C++初阶】模拟实现vector

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

【测试】pywinauto的简单使用(安装、常用对象、元素控件、鼠标操作、键盘操作)

1.说明 pywinauto是一个用于自动化Python 模块&#xff0c;适合Windows系统的软件&#xff08;GUI&#xff09;&#xff0c;可以通过Pywinauto遍历窗口&#xff08;对话框&#xff09;和窗口里的控件&#xff0c;也可以控制鼠标和键盘输入&#xff0c;所以它能做的事情比之前介…

鲁图中大许少辉博士八一新书《乡村振兴战略下传统村落文化旅游设计》山东省图书馆典藏

鲁图中大许少辉博士八一新书《乡村振兴战略下传统村落文化旅游设计》山东省图书馆典藏

数据宽度、KEIL汇编和GNU汇编的区别

数据宽度 DCB data control byte(byte) DCW data control half word(short) DCD data control word(int) DCQ data control (long)KEIL汇编和GNU汇编的区别 IDA关于please position the cursor within a funtion的解决 我是在C/C++反编译中出现的问题,因为在动态调试的时候…