【python+stata+Excel】如何构建面板数据?

本文旨在面向经管专业的初学者、低年级本科生或研究生,介绍面板数据的概念、面板数据的存储与展示逻辑、Stata中常用数据格式,以及如何通过自动化或半自动化的方法构建平衡面板数据。作为基础向的科普文章,除了介绍面板数据和小技巧外,我还希望借此帮助读者培养自己对数据结构的感觉。做到知其然,知其所以然。

1. 何为面板数据?

在经济学中,数据通常可以分为3类:

  • 横截面数据(cross-sectional data):不同个体在同一时间节点上的特征,例如,2024年3月世界各国的GDP。
  • 时间序列数据(time series data):同一个体在不同时间上的特征,例如,阿根廷1992-2024的历年GDP数据。
  • 面板数据(panel data):不同个体在不同时间上的特征,例如,中国337个城市在2008-2018年的GDP数据。

    简而言之,面板数据既含有个体维度的信息,也含有时间维度的信息。

    在实证研究过程中,我们最常接触到的就是面板数据,比如研究公司金融、区域经济、产业政策等方向。当然,如果是做宏观和数量经济的,那么你可能会更多地接触到时间序列的数据。

    2. 如何展示面板数据?

    我们已经知道,面板数据含有个体和时间双维度信息,那么,我们如何通过一种结构性方式,在计算机中存储和使用面板数据呢?

    我们以知网的中国经济社会大数据研究平台[link]为例,感受一下主流数据库是如何展示面板数据的。BTW,要登录这个平台,我们需要先访问知网,然后下研究学习平台栏目下,找到大数据研究平台,点击统计数据,进入页面后点击年度数据分析即可使用。

    我选取了北京市和天津市2005-2006年的GDP和人均GDP数据作为演示示例,这是一个很典型的面板数据。我们把行维度视为观测值(一行为一个观测),把列维度视为变量(一列为一个变量)。

    当我们选择将“时间”作为行维度时(以年份唯一标识观测值),面板数据格式如下:

    表1 以“时间”为行维度的面板数据

    北京市天津市
    GDP(亿元)人均GDP(元)GDP(亿元)人均GDP(元)
    2005年7149.8471823158.630567
    2006年8387534383538.1833411

    当我们选择将“个体”作为行维度时(以城市唯一标识观测值),面板数据则呈现如下形状:

    表2 以“个体”为行维度的面板数据

    2005年2006年
    GDP(亿元)人均GDP(元)GDP(亿元)人均GDP(元)
    北京市7149.847182838753438
    天津市3158.6305673538.1833411

    此外,我们还可以选择将“指标”作为行维度(以GDP、人均GDP唯一标识观测值),格式如下:

    表3 以“指标”为行维度的面板数据

    2005年2006年
    北京市天津市北京市天津市
    GDP7149.83158.683873538.18
    人均GDP47182305675343833411

    这三张表的共同点在于,表内的每一个数字都被“时间”-“个体”-“指标”唯一确定。比如,我们可以通过“2005年”-“北京市”-“GDP”确定到表格中的7149.8;同时每一条观测值都是被单一行维度所唯一标识的,也就是说,每个数据在行维度,要么属于北京市、要么属于天津市,要么属于2005年、要么属于2006年,要么是GDP数据、要么是人均GDP数据。而不同点仅仅在于,他们分别是被“时间”、“个体”和“指标”作为行维度所唯一标识的而已。

    上述三种方式都是存储和展示面板数据的常见方式,都是正确的,但却不是本文所介绍的重点。作为一名经管学科的同学,最常使用的一定是Stata软件,而对于Sata软件来说,常用的面板数据格式则如下所示:

    表4 Stata软件常用的面板数据格式

    YearCityGDPPGDP
    2005北京市7149.847182
    2006北京市838753438
    2005天津市3158.630567
    2006天津市3538.1833411

    对比表4和表1至表3,可以发现:(1)表4更长,而表1至表3比较宽;(2)表4每一行以Year和City两个维度共同唯一标识观测值,而表1到表3则是单一维度标识。

    表1至表4本质上没有区别,只是对面板数据进行了不同格式的存储和展示。但表4的数据格式具有较多的好处和优点:(1)时间和个体的信息以变量的形式出现,方便进行后续操作,比如说统计时间和个体的数量、生成个体和时间维度的固定效应等;(2)使我们对其他变量(如GDP、PGDP)的操作有了更多发挥空间,比如分类汇总。

    3. 如何生成面板数据?

    面板数据本身还可以进一步分类。比如说,按照时间和个体维度的相对大小,可以分为长面板和短面板;按照数据的缺失情况,可以分为平衡面板和非平衡面板。这里,我们主要介绍平衡面板的构建,一是简单常见,二是从平衡面板转非平衡面板非常容易(简单删除几个观测值即可),更具一般性。具体的操作可以由不同的软件来实现,本文主要介绍三种:Excel,Python,Stata。下面,我们以构建2000-2024年全国337个城市(地级市和直辖市)的平衡面板为例,详细介绍各种类型的软件操作。

    3.0 准备工作

    在正式开始前,我们还需要做一些简单的准备工作,即确定所需个体和时间。比如,要先确定337个城市的名称列表。在笔者后续的文章中,我会详细介绍如何通过爬虫技术最为规范地获取我国历年各级行政区的名称及代码,敬请期待。现在,假设我们已经获取了城市列表。

    3.1 使用Excel构建面板

    核心插件:Excel自带的Power Query

    核心功能:Power Query的逆透视

    第一步,将城市列表纵向依次排列,时间列表横向依次排列,如下图所示

    第二步,(表格中选中A1单元格即可)选择插入选项卡,点击表格。

    点击表格后,会弹窗一个界面,注意表数据是否选择了我们需要的部分,并记得勾选“表包含标题”,最后点击确定即可。

    确定后,界面会变成如下样式:

    第三步,查找和选择,选择定位条件,选择空值后单击确定。

    之后,你会发现表格中所有的空值单元格都被选中了。这时,鼠标无需任何操作,在用键盘键入1,然后点击ctrl按键和E,会发现所有的空值都没填充成了1.

    注意:键入什么内容并不重要,你可以键入2或者100,但不能将单元格空着,否则会影响我们下一步操作。此外,这一步也可以放到第一步的后面来做,比较灵活。

    第四步,在数据选项卡中,选择来自表格/区域。注意,由于Excel版本问题,部分读者的实际界面可能与笔者有略微差异,不必担心,选择类似功能的选项即可。

    点击后,略微等待一小会(数据量大时会比较慢),进入传说中的Power Query界面。我相信大部分读者都没有听说过这个功能,但这个Excel的功能确实非常强大。对于日常工作而言,能够熟练掌握Power Query有助于大幅提高工作效率。

    第五步,鼠标左键单击第一个时间变量(本例为2000)所在的格子(点击后相应的那列会变绿),然后拖拽下方的横向滚动条至最右侧,接着键盘按住shift按键,按住的同时,鼠标左键单机最后一个时间变量(本例为2024)所在的格子,然后松开shift按键。

    接着,我们会发现,整个表格都变为绿色了,这代表所有列都被选中了。

    第六步,鼠标右击最后一个时间变量,出现下拉菜单,选择逆透视。

    然后神奇的事情发生了,数据结构变成了我们想要的面板数据结构。

    第七步,最后一步比较简单了,左上角点击关闭并上载。

    然后我们就在Excel中得到了最基本的面板数据结构。读者可以删除不需要的变量名称,然后匹配相关的城市层面的经济社会数据,即可使用。当然,之后笔者还会写几篇文章,介绍如何对数据进行查找匹配,敬请期待啦。

    3.2 使用Pyhon构建面板

    构建思路:嵌套两个循环

    我们也可以使用python来构建我们所需要的面板数据格式。这里提供一种简单粗暴的构建方式:首先遍历城市列表,然后遍历时间列表,逐行输入“城市”-“时间”,即可完成。

    代码如下:

    import pandas as pd
    def panel_build(input_id_list,input_time_list):
        '''
        --input--
        input_id_list: the list of individuals
        input_time_list: the list of time
        -----------------------------
        --output--
        return balanced panel data
        '''
        output_id_list = []
        output_time_list = []
        for i in input_id_list:
            for j in input_time_list:
                output_id_list.append(i)
                output_time_list.append(j)
        return pd.DataFrame({'id':output_id_list,"time":output_time_list})

    例如,我们有一个city_list和一个year_list:

    city_list = ['嘉兴市', '九江市', '苏州市', 
                 '盐城市', '武汉市', '珠海市', 
                 '北京市', '上海市', '深圳市'] 
    year_list = list(range(2000,2025))

    直接使用函数即可:

    panel_build(city_list,year_list)

    最终输出如下格式:

    后续可以参考笔者的另一篇文章,把数据输出成.dta格式或者其他格式。【python】DataFrame数据保存为.dta数据-CSDN博客文章浏览阅读230次,点赞7次,收藏3次。将pandas库中常用的DataFrame数据保存为Stata软件常用的.dta数据,可对DataFrame变量使用.to_stata模块。https://blog.csdn.net/QilinCheung/article/details/136877593

    3.3 使用Stata构建面板

    构建思路:构建辅助变量,然后使用sreshape函数

    假设我们有一个城市列表的.dta数据,数据结构如下:

    代码如下:

    use city_list.dta,clear
    forvalues i = 2000(1)2024 {
    	gen year_`i' = 0 
    }
    sreshape long year_@, i(city) j(year)
    drop year_

    其中,forvalues{}这段代码运行后,会生成一系列年份变量:

    sreshape 是一个很神奇的函数,它的功能有点像3.1部分提到的Power Query的透视和逆透视,能够改变数据的结构,读者可以对比体会。

    运行命令后,会出现如下结果:

    在drop掉多余变量后,我们便得到了所需的面板数据结构。