在数据集中添加多个Excel工作表

时间:2018-08-04 19:39:40

标签: foreach append stata stata-macros

原始问题

在导入工作中的大型数据集时,我注意到一些意外行为,其中在使用append命令时,Stata似乎“忘记”了本地宏。

这似乎更奇怪,因为这似乎是该命令所特有的现象(我用save测试了,并且代码按预期工作了)。

*****************
** SET UP
******************
local datasets "auto.dta auto2.dta"
global data "/Users/Seansmac/Desktop/stata_question"
save "$data/test_data.dta", replace emptyok
local datasets "auto.dta auto2.dta"


** Save Stata data in two Excel sheets. This replicates the status of my raw data at work.
foreach dataset in `datasets'{


    di "`dataset' loaded"
     sysuse `dataset', clear
     gen data_name = "`dataset'"
     tab data_name
     export excel using "$data/auto_excel.xlsx", sheet("`dataset'") first(variables) sheetreplace
     di "`dataset' saved in excel"
     } 

*****************
** Demo of Problem
******************

import excel "$data/auto_excel.xlsx", desc

local worksheets `r(N_worksheet)'
di `worksheets'

  forvalues i = 1/`worksheets' { 
    di " Sheet number  `i'"


     local shtname`i' `r(worksheet_`i')'
     di "loading database: `shtname`i''"

     import excel "$data/auto_excel.xlsx", sheet("`shtname`i''")  clear firstrow

          di "database: `shtname`i'' loaded"

      append using "$data/test_data.dta", force

      di "database: `shtname`i'' appended"        
}


***** Show only the same data  was appended twice
     use "$data/test_data.dta", clear
     tab data_name

** I include this tab to demonstrate that only one of the two data sets is appended. 

*****************
** END
*****************

很抱歉,示例比较混乱,但是我经常发现在与本地人一起工作时使用display会有所帮助。要运行代码,所需要做的就是更改全局数据。

为了保持对工作中问题的忠诚,我加入了import excel部分;我对问题的理解不足,无法使示例变得更简单。

已修改原始问题

下面是两个代码块。第一个示例证明append命令似乎可以按预期运行(我注意到我在最初的问题中忘记使用save)。此块说明尽管将数据集附加空数据集可能并不完全直观,但仍可以正常工作。此方法的优点是,它在加载文件时无需使用条件语句。

在第二个代码块中,我尝试以相同的基本方式使用append命令,但这一次是循环的。此代码块是从Pearly Spencer复制并粘贴的,只有三个小改动:

  1. 我在开头保存了一个空数据集
  2. 我将逻辑if语句注释掉
  3. append使用了空的数据集(然后是save,因此第二次不应该为空)。

Stata“忘记”的本地宏为shtname。如果您检查display语句,则在第一个循环之后将不输出。这是我的问题所在。为了进一步说明这一点,脚本结尾处的tab命令显示变量data_name具有auto.dta的148个观测值,而没有一个auto2.dta中的。这表明相同(即第一个)数据集被追加了两次。 (对我来说)这表明脚本的append部分工作正常,但是本地marco shtname存在问题。

*演示附件出现在工作中*

clear all
cd "[**INSERT CD**]"

*Create empty data set to append later
save "test_data_noloop.dta", replace emptyok

* load first dataset
sysuse auto.dta, clear
* Gen a variable indicating what dataset it is
gen dataset = "auto_1"
* append data with empty dataset
append using "test_data_noloop.dta"
save "test_data_noloop.dta", replace

clear
*load second dataset
sysuse auto2.dta, clear
* gen dataset variable again
gen dataset = "auto_2"
* append with the previously saved dataset
append using "test_data_noloop.dta"

* Demonstrate both datasets have been appended
tab dataset

*带有小调整功能的Pearly Spencer *

clear all
cd "[**INSERT CD**]"


local datasets "auto.dta auto2.dta"

** Added the following line
save "test_data.dta", replace emptyok 

foreach dataset in `datasets'{
    display "`dataset' loaded"
    sysuse `dataset', clear
    generate data_name = "`dataset'"
    tab data_name
    export excel using "auto_excel.xlsx", sheet("`dataset'") first(variables) sheetreplace
    display "`dataset' saved in excel"
} 


import excel "auto_excel.xlsx", desc

local worksheets `r(N_worksheet)'
display `worksheets'

forvalues i = 1 / `worksheets' { 
    display " Sheet number  `i'"
    local shtname`i' `r(worksheet_`i')'
    display "loading database: `shtname`i''"
    import excel "auto_excel.xlsx", sheet("`shtname`i''")  clear firstrow
    *if `i' == 1 save "test_data.dta", replace
    display "database: `shtname`i'' loaded"
    *if `i' > 1 {
        append using "test_data.dta", force
        save "test_data.dta", replace
    *}
    display "database: `shtname`i'' appended"        
}


use "test_data.dta", clear
tab data_name

要解决注释中的某些问题,在控制台中键入sysuse dir时可以找到auto2.dta。因此,它是所有人都可以使用的数据集。我已尽力使我的代码具有可复制性,除非我没有记错,所有要做的就是将cd设置为上述代码才能正常工作。

其次,我尽力确保没有发生愚蠢的逻辑错误(如上所述,我意识到我没有在最初的问题中保存文件,这的确意味着我每次都附加一个空的数据集) 。就是说,可能是我一直在研究这个问题的时间如此之久,以至于我再也看不到树木上的木头了。因此,如果仍然是一种衬纸类型问题,请放轻松!

最后,我从未说过Stata会忘记本地宏,仅仅是因为它出现了。因此,我问这个问题是为了了解发生了什么(或更可能是我在哪里犯了错误)。

我的输出的屏幕截图 在未显示本地人的地方看到红色标记。enter image description here

***编辑#3 该图像似乎表明(至今)无法解释的行为源自append而非import

enter image description here

1 个答案:

答案 0 :(得分:1)

我的理解是,您希望将连续的Excel工作表追加到一个Stata数据集中。

下面是您的玩具示例的有效版本。

设置:

clear all
local datasets "auto.dta auto2.dta"

将Stata数据保存在两个Excel工作表中:

foreach dataset in `datasets'{
    display "`dataset' loaded"
    sysuse `dataset', clear
    generate data_name = "`dataset'"
    tab data_name
    export excel using "auto_excel.xlsx", sheet("`dataset'") first(variables) sheetreplace
    display "`dataset' saved in excel"
} 

演示该问题的解决方案:

import excel "auto_excel.xlsx", desc

local worksheets `r(N_worksheet)'
display `worksheets'

forvalues i = 1 / `worksheets' { 
    display " Sheet number  `i'"
    local shtname`i' `r(worksheet_`i')'
    display "loading database: `shtname`i''"
    import excel "auto_excel.xlsx", sheet("`shtname`i''")  clear firstrow
    if `i' == 1 save "test_data.dta", replace
    display "database: `shtname`i'' loaded"
    if `i' > 1 {
        append using "test_data.dta", force
        save "test_data.dta", replace
    }
    display "database: `shtname`i'' appended"        
}

显示结果:

use "test_data.dta", clear
tab data_name

(为了获得更好的可读性,我将代码分成不同的片段)


编辑:

Stata一次只能use 一个数据集。 append命令的工作方式是将数据从指定的外部数据集“附加”到已经加载到内存中的数据(即use d)。您的示例版本无法提供理想结果的原因是,您每次导入Excel工作表后都试图追加一个空数据集。这是逻辑上的错误。


编辑2:

生成的输出:

. clear all

. local datasets "auto.dta auto2.dta"

. 
. foreach dataset in `datasets'{
  2.     display "`dataset' loaded"
  3.     sysuse `dataset', clear
  4.     generate data_name = "`dataset'"
  5.     tab data_name
  6.     export excel using "auto_excel.xlsx", sheet("`dataset'") first(variables) sheetreplace
  7.     display "`dataset' saved in excel"
  8. } 
auto.dta loaded
(1978 Automobile Data)

  data_name |      Freq.     Percent        Cum.
------------+-----------------------------------
   auto.dta |         74      100.00      100.00
------------+-----------------------------------
      Total |         74      100.00
file auto_excel.xlsx saved
auto.dta saved in excel
auto2.dta loaded
(1978 Automobile Data)

  data_name |      Freq.     Percent        Cum.
------------+-----------------------------------
  auto2.dta |         74      100.00      100.00
------------+-----------------------------------
      Total |         74      100.00
file auto_excel.xlsx saved
auto2.dta saved in excel

. 
. import excel "auto_excel.xlsx", desc

      Sheet | Range
  ----------+----------
   auto.dta | A1:M75
  auto2.dta | A1:M75

. 
. local worksheets `r(N_worksheet)'

. display `worksheets'
2

. 
. forvalues i = 1 / `worksheets' { 
  2.     display " Sheet number  `i'"
  3.     local shtname`i' `r(worksheet_`i')'
  4.     display "loading database: `shtname`i''"
  5.     import excel "auto_excel.xlsx", sheet("`shtname`i''")  clear firstrow
  6.     if `i' == 1 save "test_data.dta", replace
  7.     display "database: `shtname`i'' loaded"
  8.     if `i' > 1 {
  9.         append using "test_data.dta", force
 10.         save "test_data.dta", replace
 11.     }
 12.     display "database: `shtname`i'' appended"        
 13. }
 Sheet number  1
loading database: auto.dta
file test_data.dta saved
database: auto.dta loaded
database: auto.dta appended
 Sheet number  2
loading database: auto2.dta
database: auto2.dta loaded
(note: variable rep78 was byte in the using data, but will be str9 now)
file test_data.dta saved
database: auto2.dta appended

. 
. use "test_data.dta", clear

. tab data_name

  data_name |      Freq.     Percent        Cum.
------------+-----------------------------------
   auto.dta |         74       50.00       50.00
  auto2.dta |         74       50.00      100.00
------------+-----------------------------------
      Total |        148      100.00

. 
end of do-file