基于python的拼接、追加等(List、Numpy、pandas)

目录

  • 动机
  • 正文
    • 一、list 追加 .append()方法
    • 二、pandas 追加 DataFrame的 .append()方法
    • 三、numpy 追加合并:concatenate, append, stack, hstack, vstack, r_, c_
      • 1. 使用 np.full() 函数创建空数组,将生成的数据按照 垂直方向的索引编号,分层塞进去
      • 2. 使用 np.dstack() 完成追加
      • 3. np.full() 与 np.dstack() 联合使用
  • 结语


动机

在python中,经常会用到拼接、追加等操作。尤其是在多波段(多时间序列的遥感数据),在合成季节、生长季数据时,需要对数据进行预处理,合成相关数据,之后再进行相关统计工作。这个过程就会涉及到对多波段tif、nc、hdf文件的追加合成工作,今天在在工作时,有了新的思路,并对相关知识进行了总结,再次记下笔记。 提示:以下是本篇文章正文内容,案例可供参考

正文

一、list 追加 .append()方法

这个应该是入门级的,一般python基础的都会。如:

#!/usr/bin/python
mms = ['01', '02', '03', '04','05', '06', '07', '08']
mms.append( '09' )
print( "mms:{}".format(mms))

对于一些方法,与numpy的array互通,我曾经见过有人通过类似的思路,求某年的某月某日是当年的多少天,对新生成的类别进行经历过的月份求和,再加上当月的天数,就得到了结果。
有人可能很笨,通过import datatime 模块,直接用当天日期减去起始日期,直接得到两个时间点相距的天数不就好了。但是我感觉还此人还是很有想法的,最起码用使用最简单的列表方式,实现了一个包的功能,很不错;简单的 .append( )方法还能实现很多功能。

二、pandas 追加 DataFrame的 .append()方法

以下是我整合数据时,用到的一段代码:

    outDF = pd.DataFrame()

    for precFile in precs:
        precDir = os.path.join(inDir,precFile)
        ndviDir = precDir.replace("pre","ndvi")
        lstDir = precDir.replace("pre","lst")

        precArr = opentif(precDir)[0]
        precArr_Reshape = precArr.reshape(-1,1)
        # print(precArr_Reshape.shape)

        ndviArr = opentif(ndviDir)[0]
        ndviArr_Reshape = ndviArr.reshape(-1,1)
        # print(ndviArr_Reshape.shape)

        print(lstDir)
        lstArr = opentif(lstDir)[0]
        lstArr_Reshape = lstArr.reshape(-1,1)
        print(lstArr)

        stackArr = np.hstack((lstArr_Reshape,ndviArr_Reshape,demArr,precArr_Reshape))
        # print(appArr)
        mask = stackArr == -3.4028234663852886e+38

        appArr = np.where(mask,np.nan,stackArr)

        newDF = pd.DataFrame(appArr).dropna()
        outDF = outDF.append(newDF, ignore_index=True)

整体思路就是:(1)对周期的几列数据进行水平拼接;(2)拼接后剔除“空值”;(3)将清洗后的数据,放入空的pd.DataFrame()中;(4)重复以上步骤,将新的时间周期数据,追加到建立好的DataFrame中去,完成数据的整合。

注意区分pandas中的两种 append 方法
(1)pandas.DataFrame.append()
(2)pandas.append()
第二种方法可以选择合并追加轴的方向。我更愿意称第一种叫做追加,第二种叫做合并。

三、numpy 追加合并:concatenate, append, stack, hstack, vstack, r_, c_

此处为其他人总结,但是的确很有用,所以我整理了下,搬到这里了。
Numpy中提供了concatenate,append, stack类(包括hsatck、vstack、dstack、row_stack、column_stack),r_和c_等类和函数用于数组拼接的操作,我最为常用的是:vstack、hsatck、dstack、concatenate。各种函数的特点和区别如下标:

函数名 功能特色
concatenate 提供了axis参数,用于指定拼接方向
append 默认先ravel再拼接成一维数组,也可指定axis
stack 提供了axis参数,用于生成新的维度
vstack 垂直拼接,沿着列的方向,对行进行拼接
hstack 水平拼接,沿着行的方向,对列进行拼接
dstack 沿着第三个轴(深度方向)进行拼接
column_stack 水平拼接,沿着行的方向,对列进行拼接
row_stack 垂直拼接,沿着列的方向,对行进行拼接
r_ 垂直拼接,沿着列的方向,对行进行拼接
c_ 水平拼接,沿着行的方向,对列进行拼接

在使用以上函数时,首先需要弄清楚的轴的方向(这是别人说的);但是一直没有细细的理这些东西,因为在使用 vstack、hsatck、dstack 这几函数时,如何合并的方向不对,他会报错,并且你用print()函数打印输出一下拼接前后的 .shape 的变化,就能清楚自己的自己合并的正确与否。

我的方法是不可取的,我一般处理问题都是问题导向,通过验证结果与自己想的是否一致,判断自己的代码是否有问题;但是作为一个真正想用好代码的人来说,要“知其然,知其所以然”,我后面有时间也会花时间弄清楚的。

对于遥感数据的处理,通常需要将二维数组,在垂直方向上合成,生成三维数组,我的处理方案有两种:

1. 使用 np.full() 函数创建空数组,将生成的数据按照 垂直方向的索引编号,分层塞进去

这个是我原来一直使用的方法,还算好用;创建全部是np.nan的一个数组;无论是在垂直方向上求和(np.nansum)、均值值(np.nanmean)、最大值合成(np,nanmax),都比较顺手。但是有一个缺点就是,面对不同的处理场景数据(春季、夏季、年)必须对数据的 shape 参数进行设计,没有append方法来的方便;因为 append 方法是有多少数据,直接在后面追加,之后再一同进行求和、均值值、最大值合成等处理。因此对shape 参数的设计 为此种方法的一种缺陷,基于此方法设计了第二种方案。

2. 使用 np.dstack() 完成追加

因为所读取的数据均为1个 .nc 文件提供,因此每一层其形状都一样,因此可以直接拿过来,然后使用 i =i +1 类似的思路,不断更新,追加,完成对所需数据的遍历。但此方法也有一个缺陷,那就是他需要有一个初始的“ arrFirst ”数据,不断对其更新,追加,有时就是因为第一层的2维数据的建立,使得复杂程度与 1. 方案接近。

  arrFirst = ncVariable.loc['{}-06-15T22:30:00.000000000'.format(yyyy)].data
	   print(arrFirst.shape)
	   for mm in range(7,9):
	       # 此处注意: 不加入 str 的 timeSer 为 numpy.datetime64 ,不能使用 .startswith() 及 .split() 方法
	       # 最终返回的 loc_Second 的数据类型依然为 numpy.datetime64 数据类型
	       loc_Second = [timeSer for timeSer in list(timeSerises)
	                    if str(timeSer).startswith(str(yyyy))
	                                          and str(mm) in str(timeSer).split("-")[1]
	                                          ][0]
	       # print(type(loc_Second))
	       arrSecond = ncVariable.loc[loc_Second].data
	       print("arrSecond:{}".format(arrSecond.shape))
	       # 通过 np.stack 不断更新 arrFirst,添加层次
	       arrFirst = np.dstack([arrFirst,arrSecond])

3. np.full() 与 np.dstack() 联合使用

因为最终得到的结果,可能是得到每个像元位置的均值,最大值。因此可以通过 np.full() 方法,初始化一个np.nan 的二维数组,然后在其上进行垂直维度的叠加;这样的最终结果,会比本应该合成的数据多一层,因此不能直接使用 np.mean 方法进行数据合成,层数多一层会使得分母变大,均值偏小;但是由于创建的是通过 np.nan初始化的2维数组,因此可以使用 np.nanmean 方法进行数据的合成。

结语

我的这几种方法,只要你从事的是遥感研究,使用的是python语言,一定会有所帮助。其实我这里还有很多一直从事遥感事业过程中积累点滴代码,但是由于时间不是那么的充分,也没时间写博客,但是我想我写出来的每一篇博客,对看过他的人有所帮助。(其实我的博客都是数据的基础处理,没有什么高阶的)

你可能感兴趣的:(遥感,Anaconda,python,numpy,数据分析)