将SIC映射到FamaFrench行业分类

时间:2017-08-09 00:25:51

标签: r regex sqldf

我正在开展一个项目,我必须将具有SIC行业分类的公司映射到相应的Fama-French行业分类。我发现Ian Gow已经优雅地创建了脚本来执行此操作。该脚本可从以下网址获得:https://iangow.wordpress.com/2011/05/17/getting-fama-french-industry-data-into-r/

但是,脚本或数据集中存在故障,出于某种原因,它不适用于“Siccodes30.txt”。更具体地说,它不会产生与“Siccodes30.txt”中与“6726-6726 Unit inv trusts,closed-end”相关的行的正确结果(映射)。我一直试图找出问题的根源,但我还没有成功。

在下面的帖子中,我已经包含了原始脚本(有一些空间可以提高效率)并且我在最后添加了几行以使其与在线示例一起使用。

原始脚本(我删除了评论以缩短帖子)。同样,这不是我的脚本(原始脚本在https://iangow.wordpress.com/2011/05/17/getting-fama-french-industry-data-into-r/

url4FF <- paste("http://mba.tuck.dartmouth.edu",
             "pages/faculty/ken.french/ftp",
             "Industry_Definitions.zip", sep="/")
f <- tempfile()
download.file(url4FF, f)
fileList <- unzip(f,list=TRUE)
trim <- function(string) {
ifelse(grepl("^\\s*$", string, perl=TRUE),"",
       gsub("^\\s*(.*?)\\s*$","\\1",string,perl=TRUE))
}
extract_ff_ind_data <- function (file) {
ff_ind <- as.vector(read.delim(unzip(f, files=file), header=FALSE, 
                           stringsAsFactors=FALSE))
ind_num <- trim(substr(ff_ind[,1],1,10))
for (i in 2:length(ind_num)) {
    if (ind_num[i]=="") ind_num[i] <- ind_num[i-1]
}
sic_detail <- trim(substr(ff_ind[,1],11,100))
is.desc <- grepl("^\\D",sic_detail,perl=TRUE)
regex.ind <- "^(\\d+)\\s+(\\w+).*$"
ind_num <- gsub(regex.ind,"\\1",ind_num,perl=TRUE)
ind_abbrev <- gsub(regex.ind,"\\2",ind_num[is.desc],perl=TRUE)
ind_list <- data.frame(ind_num=ind_num[is.desc],ind_abbrev,
                       ind_desc=sic_detail[is.desc])

regex.sic <- "^(\\d+)-(\\d+)\\s*(.*)$"
ind_num <- ind_num[!is.desc]
sic_detail <- sic_detail[!is.desc]
sic_low  <- as.integer(gsub(regex.sic,"\\1",sic_detail,perl=TRUE))
sic_high <- as.integer(gsub(regex.sic,"\\2",sic_detail,perl=TRUE))
sic_desc <- gsub(regex.sic,"\\3",sic_detail,perl=TRUE)
sic_list <- data.frame(ind_num, sic_low, sic_high, sic_desc)

return(merge(ind_list,sic_list,by="ind_num",all=TRUE))
}

FFID_30 <- extract_ff_ind_data("Siccodes30.txt")

我添加了以下行以允许测试脚本:

library(gsheet)
url <-"https://docs.google.com/spreadsheets/d/1QRv8YmJv0pdhIVmkXMQC7GQuvXV21Kyjl9pVZsSPEAk/gid=1758600626"
companiesSIC <- read.csv(text=gsheet2text(url, format='csv'), stringsAsFactors=FALSE)
names(companiesSIC)

library(sqldf)
companiesFFID_30 <- sqldf("SELECT a.gvkey, a.SIC, b.ind_desc AS FF30, 
    b.ind_num as FFIndNUm30
FROM companiesSIC AS a
  LEFT JOIN FFID_30 AS b
  ON a.sic BETWEEN b.sic_low AND b.sic_high")
companiesFFID_30

第141行和第142行的结果是错误的。而不是行业编号,提供字符串。

由于

PS正如我所说,有足够的空间让脚本更短(例如,你不需要创建一个单独的函数来删除空格,你可以使用trimws)但是要归功于原作者,我保持脚本的原始形式。但是,如果有人可以解决问题,也应该尝试更新脚本的其余部分。

1 个答案:

答案 0 :(得分:0)

脚本没有任何问题。问题在于格式化txt文件的两行(141和142)。

我用文本编辑器打开文本文件,删除并重新输入这两行的内容。当我重新运行R脚本时,问题就消失了。