当前位置:   article > 正文

Stata 字符变量处理_stata中字符串数据怎么处理

stata中字符串数据怎么处理

Stata 中经常需要对 字符变量 做处理,将 字符变量 转换为 数值变量。但 字符变量 的形式多样,包括 标识符变量/分类变量日期变量纯数字变量 等,在转换过程中需要使用不同的转换方法。尤其当字符串内容为数字时(如 日期变量纯数字变量),需要格外小心。

本篇推文将提供七个建议,涵盖多种字符串形式的处理方法,帮助大家更好的处理字符型变量。

1. 保留备份

1.1 保留原始数据

  • 保留原始 dta 数据 使用 save 命令将修改后的数据另存为新的 .dta 文件,不要直接修改替换原始数据。
  • 保留导入的原始数据 不要丢弃用于导入( import)数据的任何原始数据文件,例如文本或电子表格文件。有时,可能需要返回到源头并重新开始数据导入和处理工作。

1.2 保留原始变量

因为字符串转换很容易出错,所以在字符串操作过程中,通常生成一个新的变量来保存转换结果,而不是替换原有的字符串变量。有些命令提供 replace 选项,可以将原始变量替换为转换后的结果,但这种情况下,如果转换出错将找不到原始的字符串变量。更好的方式是使用 generate() 选项生成新的变量,如果出现错误,也可以回到原始变量,重新修改。

译者注: 需要补充说明的是,如果遵循了第一条建议,即我们的 do 文档 的首行始终是以 import xxx.txtimport xxx.xlsx 的方式导入原始 TXT 或 Excel 文档,那么可以在 dofile 中采用 replace 的方式替换到原变量,以免产生过多的新变量。后续处理过程中若需返回,则可以重新导入原始数据。

2. “日期型”字符串变量

使用 listeditbrowse 命令查看字符串变量,如果变量中包含形如 20jan2010 09:15:2220/01/20102010w32010q1 的数据,这种变量就是**“日期型”**字符串变量,通常包含以下几种类型:

日期类型该类型的显示格式
datetime20jan2010 09:15:22.120
(daily) date20jan2010, 20/01/2010, ...
weekly date2010w3
monthly date2010m1
quarterly date2010q1
half-yearly date2010h1
yearly date2010

2.1 日历年(yearly date)

如果日期型变量是以字符串保存的形如 19842018 这样的年度日期,可以直接使用 destring 命令转换为数值格式,具体见 help destring

2.2 包含日期的字符串变量

如果字符串变量包含日期或时间,需要使用日期-时间函数转换为数字格式的日期或时间变量。具体转换过程可以分为如下两个步骤: Step 1: 使用日期-时间函数 help datetime,将字符串日期转换为数字日期 Step 2: 使用 format 命令,将数字显示为想要的日期格式

2.2.1 数字日期

数字日期,可以理解为某一日期距离原点时间间隔。Stata 将 1960 年的第一个日期设为原点 0(如:日度数据的原点为 1960年1月1日;月度数据的原点为 1960 年第 1 月;周数据的原点为 1960 年第 1 周)。不同的日期类型,计算时间间隔的单位不同(如:日度数据为 间隔天数,月度数据为 间隔月数,周数据为 间隔周数)。

以日度数据为例,1776年7月4日 的数字日期是 -67019,表示 1960年1月1日 之前的第67019 天。从这里可以看出一个问题:对于字符串日期来说,含义是很直观的;但对于数字日期,含义通常比较模糊(如 67019),很难直观判断这个数字代表的是什么日期。可以通过 format 命令,将数字日期显示为日期格式,详情参见 help format

format 的语法为 format varlist %fmt,其中 varlist 为数字日期变量,%fmt 为显示的日期格式,需要与日期类型相对应(如:日度数据的日期格式为 %td)。常见的日期类型与对应的日期显示格式如下表所示:

日期格式 %fmt日期类型举例
%tcdate/timeformat varlist %tc
%tCdate/timeformat varlist %tC
%tddateformat varlist %td
%twweekformat varlist %tw
%tmmonthformat varlist %tm
%tqquarterformat varlist %tq
%thhalf-yearformat varlist %th
%tyyearformat varlist %ty
%tggenericformat varlist %tg
2.2.2 日期-时间函数

日期-时间函数 的功能是将文本日期转换为数字日期,可以通过 help datetime 查找。具体使用哪一个函数,根据字符串变量的日期类型确定。比如对于日度数据 20jan2010,可以使用 date() 或者 daily() 函数。(这两个函数的功能是一样的,但 daily() 的函数名更直观,所以推荐使用 daily() 函数。)

举个简单的例子:

. clear
. set obs 1
. gen strDate = "July 4, 1776" //生成“日期型”字符串变量
  • 1
  • 2
  • 3
  • 4

*-(一)根据日期函数 daily(),

  • 将 字符串日期(strDate) 转换为 数字日期(numDate)
    . gen numDate = daily(strDate, “MDY”)
    . list
    ±-----------------------+
    strDate numDate
  1. | July 4, 1776 -67019 |
    ±-----------------------+

*-(二)设定数字日期(numDate)的显示格式
. format numDate %td
. list
±-------------------------+
| strDate numDate |
|--------------------------|

  1. | July 4, 1776 04jul1776 |
    ±-------------------------+

上述代码中,daily() 函数将字符串日期 "July 4, 1776" 转换成数字日期 -67019,这个数值是 "1776年7月4日" 距离原点 "1960年1月1日" 的天数。format 命令将数字日期 -67019 显示为日度数据格式 04jul1776

2.3 例子:日度数据形式的季度数据

(1)对于字符串形式的季度数据 "2018q1"、"2018q2",可以通过 quarterly() 函数转换为数字形式的季度数据。

(一)生成字符串形式的季度数据
. clear
. set obs 2
. input str20 date
        date
  1.  "2018q1"
  2.  "2018q2"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(二)将字符串形式的季度数据(date)转换为 数字形式的季度数据(numdate)
. gen numdate = quarterly(date, “YQ”)
. format numdate %tq
. list
±-----------------+
| date numdate |
|------------------|

  1. | 2018q1 2018q1 |
  2. | 2018q2 2018q2 |
    ±-----------------+

(2)如果用每一季度的最后一天(日度数据形式)来表示季度数据,如 "2018-3-31"、"2018-6-30",如何将字符串转换为数字形式的季度数据格式(2018q1、2018q2)? help datetime 可以找到不同类型的数字日期之间的转换函数,其中 qofd() 函数可以将数字形式的日度数据转换为数字形式的季度数据,结合 daily() 函数,可以很好的解决上述问题。

解决方案: qofd(daily()),具体实现过程如下:

* (一)生成日度数据形式的季度数据
. clear
. set obs 2
. input str20 date
         date
  1. "2018-3-31"
  2. "2018-6-30"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • (二)(1)将字符串形式的日度数据(date)转换为 数字形式的日度数据(daily)
  •  (2)将数字形式的日度数据(daily)转换为数字形式的季度数据(quarter)
    
    • 1

. gen daily = daily(date, “YMD”)
. gen quarter = qofd(daily)
. list
±----------------------------+
| date daily quarter |
|-----------------------------|

  1. | 2018-3-31 21274 232 |
  2. | 2018-6-30 21365 233 |
    ±----------------------------+
  • (三)设定日期的显示格式
    . format daily %td
    . format quarter %tq
    . list
    ±--------------------------------+
    date daily quarter
    1.
    2.
    ±--------------------------------+

3. 标识符变量、分类变量

对于标识符变量(如:公司、国家、地区名称)或者分类变量,可以通过 (1)encode命令;(2)egen 命令的 group() 函数 两种方式,将字符变量映射到数字变量。

在开始之前,我们生成一个分类变量,用以详细说明两种命令的使用方式:

// 生成一个 yesno 变量,保存为 yesno.dta 数据。
// yesno 是一个分类变量,包括三个取值(yes,no,Dont know)
clear
set obs 3
input str20 yesno
	"Yes"
	"No"
	"Dont know"
save yesno.dta, replace
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.1 encode 命令

默认情况下,Stata 中的 encode 命令会将字符变量按字母排序。字符变量的不同取值,按照排列顺序分别映射到数值 1,2,...,并且为生成的数字变量添加值标签,用以说明字符串-数字的对应关系。

encode 命令的语法为:

encode varname [if] [in], generate(newvar) [label(name)]
  • 1
  • 2

其中 varname 为需要转换为数字的分类/标识符变量;选项 generate(newvar) 表示生成新的变量(newvar)存储转换后的结果;选项 label(name) 表示按照变量值标签(name)中的“字符串-数字”的对应关系来转换(默认按照字母排序转换)。

* (一)查看数据:变量 yesno 中包括三个取值("Yes", "No", "Dont know")
. use yesno.dta, clear
. list
     +-----------+
     |     yesno |
     |-----------|
  1. |       Yes |
  2. |        No |
  3. | Dont know |
     +-----------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • (二)生成两个变量值标签(yesno1, yesno2)
    . label define yesno1 1 “Yes” 2 “No” 3 “Don’t know”
    . label define yesno2 1 “Yes” 2 “No” 3 “Dont know”
    . label list
    yesno2:
    1 Yes
    2 No
    3 Dont know
    yesno1:
    1 Yes
    2 No
    3 Don’t know

  • (三)将字符变量 yesno 转换为数值变量
    . encode yesno, gen(newvar) //按默认排序(字母顺序)转换
    . encode yesno, gen(newvar1) label(yesno1) //按值标签 yesno1的“字符串-数字”对应关系转换
    . encode yesno, gen(newvar2) label(yesno2) //按值标签 yesno2的“字符串-数字”对应关系转换
    . label list
    yesno1:
    1 Yes
    2 No
    3 Don’t know
    4 Dont know
    newvar:
    1 Dont know
    2 No
    3 Yes
    yesno2:
    1 Yes
    2 No
    3 Dont know

. list, nolab //生成的三个转换变量的数字取值情况
±---------------------------------------+
| yesno newvar newvar1 newvar2 |
|----------------------------------------|

  1. | Yes 3 1 1 |
  2. | No 2 2 2 |
  3. | Dont know 1 4 3 |
    ±---------------------------------------+

. list //显示三个转换变量的值标签
±----------------------------------------------+
| yesno newvar newvar1 newvar2 |
|-----------------------------------------------|

  1. | Yes Yes Yes Yes |
  2. | No No No No |
  3. | Dont know Dont know Dont know Dont know |
    ±----------------------------------------------+

可以看出,当使用值标签 yesno1 时,由于值标签中没有 dont know 的数字对应关系,Stata 会自动在值标签后面追加一个数字,作为 dont know 字符串的映射。

3.2 egen 的 group() 函数

egen 命令的 group() 函数可以起到同样的效果: egen newvar = group(varname), label,其中 varname 为标识符/分类变量,newvar 为生成的数值变量,选项 label 表示按字母顺序添加值标签(默认情况下不添加值标签)。

. use yesno.dta, clear
. egen b = group(yesno)
. egen b1 = group(yesno), label
  • 1
  • 2
  • 3
  • 4

. label list
b1:
1 Dont know
2 No
3 Yes

. list, nolab
±-------------------+
| yesno b b1 |
|--------------------|

  1. | Yes 3 3 |
  2. | No 2 2 |
  3. | Dont know 1 1 |
    ±-------------------+
    . list
    ±--------------------------+
    yesno b b1
  4. | Yes 3 Yes |
  5. | No 2 No |
  6. | Dont know 1 Dont know |
    ±--------------------------+

3.3 分类变量转换中的常见问题

如果字符串中存在多余的空格,比如 "I Love Python"" I Love Python""I Love Python "" I Love Python",Stata 会认为这是四个不同的字符串,转换为数字变量的时候,也会对应到四个不同的数字。在处理这类问题的时候,通常使用 trim() itrim() 函数,去掉字符串两端的空格,或者规范字符串内部的空格,将上述四个字符串处理成相同的字符串 "I Love Python"。具体详见 help string functions

4. 某些字符串标识变量可以不作转换

有些字符串变量可以保留为字符串形式,没必要转换成数字格式。比如:

  • 当出现异常时,根据标识变量检查个别案例;
  • 使用标识变量合并其他数据集(参见 [D] merge);
  • 唯一标识符提供了以特定顺序获取数据集的标准、可重复的方式。

5. 不要导入元数据

数据中可能包含一些与数据的定义、解释、注释相关的信息(元数据),这类信息可以作为变量名称、变量标签、值标签或注释等反映到数据中。有时元数据也会解释缺失值或异常值的产生原因及编码方式,这些文字说明很有用,但这些文字并不需要全部包含在数据集中。

Stata 并不能识别哪些文字是说明性的文字,不需要读入;哪些文字是数据的一部分,需要以数据形式读入;哪些文字可以作为变量名或者变量标签。如果直接使用 import 命令,Stata 会将所有文本全部导入数据中,生成很多的字符变量来存储元数据中的文字信息。但很多时候并不需要这些元数据,或者有些元数据仅需要作为变量名称、变量标签,此时需要从导入的数据中删除或者处理元数据信息。

针对元数据信息,通常有两种处理方式: (1)如果已经导入了元数据,可以根据具体情况,删除不需要的元数据所在的行;使用 destring 命令将元数据导致的字符变量转换为数字变量。 (2)重新导入数据(import excelimport delimited),使用 import 命令提供的选项,可以跳过数据文件中元数据所在的行和列,也可以将首行内容作为变量标签或者变量名。

6. 最常用的 destring 命令

字符串变量主要可以分为 “日期型”字符变量、“标识变量/分类变量”、由于元数据的存在导致的字符变量。对于“日期型”字符变量,使用日期-时间函数 help datetime 转换为数值变量;对于“标识变量/分类变量”,使用 encode varnameegen newvar = group(varname) 两种方式编码为数值变量;如果是元数据造成的字符变量,通过 import 选项 或者 drop 元数据所在行 来删除元数据。

若逐个排除了上述过程,剩下的字符变量通常可以使用 destring 来转换为数值变量。Stata 会以数字格式读入纯数字变量,但如果变量中包含非数字内容(如将 110 误写为 11o),或者受到了元数据污染(如:数字变量的最后几行写了一些注释信息),则这些纯数字内容会以字符串的形式导入数据,形成字符变量。当删除元数据以后,纯数字形成的字符变量可以使用 destring 命令转换为数值变量。

destring 命令有点类似于 real() 函数,可以将字符串形式的数字转换成数值形式的数字,但 destring 更灵活的地方在于提供了很多选项,可以处理字符变量中的非数字形式的字符,比较常用的几个选项包括 forceignore()percentdpcomma

force 选项将纯数字字符转换成数字,同时强制将无法识别的字符处理成缺失值,是不得已情况下才会使用的选项;ignore("chars") 选项去除字符中的 "chars" 字符,将剩余的内容转换为数字。percent 选项将数字字符串转换成小数形式;dpcomma 选项将字符中的逗号作为小数点转换为十进制格式(如 "12,3" 转换为 12.3)。

我们生成一个字符串变量,用来详细介绍各个选项的用途。

// 生成字符串变量
clear
set obs 7
input str20 whatever
	"209"
	"1560"
	"52o"
	"ll9"
	"NA"
	"12,3"
	"79%"
save temp.dta, replace
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

各选项的使用方法和结果如下:

. // force 选项
. use temp.dta, clear
. destring whatever, generate(wanted) force
. list, sep(0)
     +-------------------+
     | whatever   wanted |
     |-------------------|
  1. |      209      209 |
  2. |     1560     1560 |
  3. |      52o        . |
  4. |      ll9        . |
  5. |       NA        . |
  6. |     12,3        . |
  7. |      79%        . |
     +-------------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

. //ignore 选项
. use temp.dta, clear
. destring whatever, generate(wanted) ignore(“NA%ol,”)
. list, sep(0)
±------------------+
| whatever wanted |
|-------------------|

  1. | 209 209 |
  2. | 1560 1560 |
  3. | 52o 52 |
  4. | ll9 9 |
  5. | NA . |
  6. | 12,3 123 |
  7. | 79% 79 |
    ±------------------+

. //dpcomma 选项
. use temp.dta, clear
. destring whatever, generate(wanted) ignore(“NAlo%”) dpcomma
. list, sep(0)
±------------------+
| whatever wanted |
|-------------------|

  1. | 209 209 |
  2. | 1560 1560 |
  3. | 52o 52 |
  4. | ll9 9 |
  5. | NA . |
  6. | 12,3 12.3 |
  7. | 79% 79 |
    ±------------------+

. //percent 选项
. use temp.dta, clear
. destring whatever, generate(wanted) ignore(“NAlo”) percent dpcomma
. list, sep(0)
±------------------+
| whatever wanted |
|-------------------|

  1. | 209 2.09 |
  2. | 1560 15.6 |
  3. | 52o .52 |
  4. | ll9 .09 |
  5. | NA . |
  6. | 12,3 .123 |
  7. | 79% .79 |
    ±------------------+

7. 找出无法转换的内容

destring 可以将纯数字的字符串转换成数字格式,如果变量中包含某些特殊字符(如输入错误: 52o;缺失值:NA;百分号:%),我们需要使用 destring 的选项来处理这些特殊字符。为了更好的使用 destring 选项,我们希望查看 destring 无法自动处理的内容。

具体查看命令:tabulate whatever if missing(real(whatever)),其中 whatever 为需要转换成数字的字符串变量。

// 原始数据中包含一个变量:whatever
. use temp.dta, clear
. list, sep(0)
     +----------+
     | whatever |
     |----------|
  1. |      209 |
  2. |     1560 |
  3. |      52o |
  4. |      ll9 |
  5. |       NA |
  6. |     12,3 |
  7. |      79% |
     +----------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

// 打印 destring 无法转换的内容
. tabulate whatever if missing(real(whatever))

        whatever |      Freq.     Percent        Cum.
  • 1

---------------------±----------------------------------
12,3 | 1 20.00 20.00
52o | 1 20.00 40.00
79% | 1 20.00 60.00
NA | 1 20.00 80.00
ll9 | 1 20.00 100.00
---------------------±----------------------------------
Total | 5 100.00

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/534600
推荐阅读
相关标签
  

闽ICP备14008679号