从谷歌电子表格中将数据导入R

58

谷歌电子表格发布选项似乎有所变化。不再可以将其发布为CSV或tab文件以供Web使用(请参见最近的帖子)。因此,使用RCurl从谷歌电子表格中导入数据到R的常规方法不再起作用:

require(RCurl)
u <- "https://docs.google.com/spreadsheet/pub?hl=en_GB&hl=en_GB&key=0AmFzIcfgCzGFdHQ0eEU0MWZWV200RjgtTXVMY1NoQVE&single=true&gid=4&output=csv"
tc <- getURL(u, ssl.verifypeer=FALSE)
net <- read.csv(textConnection(tc))

有人有解决办法吗?


1
如果您能分享一下您所认为的“通常方式”,那可能会有所帮助。此外,我似乎仍然可以使用Google电子表格将数据发布到Web上的CSV格式。 - A5C1D2H2I1M1N2O1R2T1
1
有一个名为gspreadr的软件包,可以从R中访问和管理Google电子表格。 - Ben
1
@Ben 非常好的建议,但请注意软件包名称已更改,不再是 googlesheets(https://github.com/jennybc/googlesheets),也可在 CRAN 上获得。 - Andrie
10个回答

61

我刚刚写了一个简单的包来解决这个问题:只使用URL下载Google表格。

install.packages('gsheet')
library(gsheet)
gsheet2tbl('docs.google.com/spreadsheets/d/1I9mJsS5QnXF2TNNntTy-HrcdHmIF9wJ8ONYvEJTXSNo')

更多细节在这里:https://github.com/maxconway/gsheet


2
好的简单解决方案 - user3375672
我喜欢它,因为它很简单,而且不需要授权就可以查看表格! - Alessandro Jacopson

56
使用Jenny Bryan开发的Google Sheets R API googlesheets4 包,这是分析和编辑Google Sheets数据的最佳方式。它不仅可从Google Sheets中提取数据,还可以在Google Sheets中编辑数据、创建新表等。

该包可通过install.packages("googlesheets4")安装。

有一个入门的vignette,请参见她的GitHub存储库获取更多信息。如果需要,您也可以从该GitHub页面安装包的最新开发版本。


10
请在这个回答中包含一些该软件包的基本用法。 - MichaelChirico
13
为了方便大家以后的使用,现在 googlesheets 包已经被停用。googlesheets4 是它的替代品。 - zack

15

我正在研究解决方案。这里是一个可以处理您的数据以及我的几个Google电子表格的函数。

首先,我们需要一个从Google表格中读取数据的函数。readGoogleSheet()会返回一个数据框列表,其中每个数据框都对应于在Google表格上找到的一个表:

readGoogleSheet <- function(url, na.string="", header=TRUE){
  stopifnot(require(XML))
  # Suppress warnings because Google docs seems to have incomplete final line
  suppressWarnings({
    doc <- paste(readLines(url), collapse=" ")
  })
  if(nchar(doc) == 0) stop("No content found")
  htmlTable <- gsub("^.*?(<table.*</table).*$", "\\1>", doc)
  ret <- readHTMLTable(htmlTable, header=header, stringsAsFactors=FALSE, as.data.frame=TRUE)
  lapply(ret, function(x){ x[ x == na.string] <- NA; x})
}

接下来,我们需要一个函数来清理每个表格。 cleanGoogleTable()会删除Google插入的空行,删除行名称(如果存在),并允许您在表格开始之前跳过空行:

接下来,我们需要一个函数来清理每个表格。 cleanGoogleTable()会删除Google插入的空行,删除行名称(如果存在),并允许您在表格开始之前跳过空行:
cleanGoogleTable <- function(dat, table=1, skip=0, ncols=NA, nrows=-1, header=TRUE, dropFirstCol=NA){
  if(!is.data.frame(dat)){
    dat <- dat[[table]]
  }

  if(is.na(dropFirstCol)) {
    firstCol <- na.omit(dat[[1]])
    if(all(firstCol == ".") || all(firstCol== as.character(seq_along(firstCol)))) {
      dat <- dat[, -1]
    }
  } else if(dropFirstCol) {
    dat <- dat[, -1]
  }

  if(skip > 0){
    dat <- dat[-seq_len(skip), ]
  }

  if(nrow(dat) == 1) return(dat)


  if(nrow(dat) >= 2){
    if(all(is.na(dat[2, ]))) dat <- dat[-2, ]
  }
  if(header && nrow(dat) > 1){
    header <- as.character(dat[1, ])
    names(dat) <- header
    dat <- dat[-1, ]
  }

  # Keep only desired columns
  if(!is.na(ncols)){
    ncols <- min(ncols, ncol(dat))
    dat <- dat[, seq_len(ncols)]
  }


  # Keep only desired rows
  if(nrows > 0){
    nrows <- min(nrows, nrow(dat))
    dat <- dat[seq_len(nrows), ]
  }

  # Rename rows
  rownames(dat) <- seq_len(nrow(dat))
  dat
}

现在我们已经准备好读取你的Google表格:

> u <- "https://docs.google.com/spreadsheets/d/0AmFzIcfgCzGFdHQ0eEU0MWZWV200RjgtTXVMY1NoQVE/pubhtml"
> g <- readGoogleSheet(u)
> cleanGoogleTable(g, table=1)


         2012-Jan Mobile internet Tanzania
1 Airtel Zantel Vodacom Tigo TTCL Combined


> cleanGoogleTable(g, table=2, skip=1)

                           BUNDLE       FEE VALIDITY     MB    Cost Sh/MB
1             Daily Bundle (20MB)     500/=    1 day     20     500  25.0
2            1 Day bundle (300MB)   3,000/=    1 day    300   3,000  10.0
3             Weekly bundle (3GB)  15,000/=   7 days  3,000  15,000   5.0
4            Monthly bundle (8GB)  70,000/=  30 days  8,000  70,000   8.8
5         Quarterly Bundle (24GB) 200,000/=  90 days 24,000 200,000   8.3
6            Yearly Bundle (96GB) 750,000/= 365 days 96,000 750,000   7.8
7 Handset Browsing Bundle(400 MB)   2,500/=  30 days    400   2,500   6.3
8                        STANDARD      <NA>     <NA>      1    <NA>  <NA>

2
尝试这个,但是出现了Error in file(con, "r") (from #5) : cannot open the connection的错误,你有什么想法是什么原因导致的吗? - slackline
1
此代码已经过时。请使用建议的googlesheets包,如接受的答案所示。 - Andrie

12

不确定其他用例是否更复杂,或者在此期间是否有任何更改。 将电子表格以CSV格式发布后,这个简单的一行代码适用于我:

myCSV<-read.csv("http://docs.google.com/spreadsheets/d/1XKeAajiH47jAP0bPkCtS4OdOGTSsjleOXImDrFzxxZQ/pub?output=csv")

R版本3.3.2 (2016-10-31)



10

即使您在代理后面,也有一种最简单的方法来获取Google表格。

require(RCurl)
fileUrl <- "https://docs.google.com/spreadsheets/d/[ID]/export?format=csv"
fileCSV <- getURL(fileUrl,.opts=list(ssl.verifypeer=FALSE))
fileCSVDF <-  read.csv(textConnection(fileCSV))

4

更简单的方式。

请务必仔细匹配您的URL与此处示例的格式相匹配。您可以从Google电子表格编辑页面获取除/export?format=csv之外的所有内容。然后,只需手动将此片段添加到URL中,然后按照此处所示使用即可。

library(RCurl)
library(mosaic)
mydat2 <- fetchGoogle(paste0("https://docs.google.com/spreadsheets/d/",
  "1mAxpSTrjdFv1UrpxwDTpieVJP16R9vkSQrpHV8lVTA8/export?format=csv"))
mydat2

2

使用httr和XML包来抓取HTML表格。

library(XML)
library(httr)

url <- "https://docs.google.com/spreadsheets/d/12MK9EFmPww4Vw9P6BShmhOolH1C45Irz0jdzE0QR3hs/pubhtml"

readSpreadsheet <- function(url, sheet = 1){
  library(httr)
  r <- GET(url)
  html <- content(r)
  sheets <- readHTMLTable(html, header=FALSE, stringsAsFactors=FALSE)
  df <- sheets[[sheet]]
  dfClean <- function(df){
    nms <- t(df[1,])
    names(df) <- nms
    df <- df[-1,-1] 
    row.names(df) <- seq(1,nrow(df))
    df
  }
  dfClean(df)
}
df <- readSpreadsheet(url)
df

这将为我获取一行,但没有列。 - Elin
这对我来说是一个有效的解决方案。但是在结果数据框中,我的标题下面有一行空行。 - hianalytics
@hianalytics,你应该可以调整dfClean函数,以匹配你的电子表格特定的格式。 - jpmarindiaz
@jpmarindiaz 太好了,谢谢!在脚本末尾添加 df < df[-1,] 对我非常有效。我认为 Google 电子表格可能存在问题,因为在最初读取数据后,在标题下方添加了一行额外的行 readHTMLTable(... - hianalytics
更正:df <- df[-1,] 我还在 Google Sheet 中将第一行冻结了,我相信这是导致额外空白行的原因,因为在我取消冻结后,重新运行 @jpmarindiaz 提供的原始脚本时,它消失了。 - hianalytics

0

2
@Andrie:我真的很喜欢这个解决方案,尤其是在阅读了你的博客文章之后,我感到非常兴奋,因为这是可扩展的并且易于复制的工作流程。但是它没有起作用,我收到了这个错误 readGoogleSheet(gdoc) Error in file(con, "r") : cannot open the connection - hianalytics

0

截至2015年5月,仍然可以使用隐藏的URL <sheeturl>/export?format=csv技巧1从Google电子表格中获取CSV文件。

然而,在解决了这个问题之后,又会遇到另一个问题 - 数字的格式根据表格的语言环境进行设置,例如在“美国”表格中可能会得到1,234.15,而在“德国”表格中可能会得到1.234,15。要确定表格的语言环境,请转到Google文档中的“文件”>“电子表格设置”。

现在,您需要从数字列中删除小数点,以便R可以解析它们;根据您的数字有多大,可能需要对每个列执行多次此操作。我编写了一个简单的函数来完成这个任务:

# helper function to load google sheet and adjust for thousands separator (,)
getGoogleDataset <- function(id) {
  download.file(paste0('https://docs.google.com/spreadsheets/d/', id, '/export?format=csv'),'google-ds.csv','curl');
  lines <- scan('google-ds.csv', character(0), sep="\n");

  pattern<-"\"([0-9]+),([0-9]+)";
  for (i in 0:length(lines)) {
    while (length(grep(pattern,lines[i]))> 0) {
      lines[i] <- gsub(pattern,"\"\\1\\2",lines[i]);
    }
  }
  return(read.csv(textConnection(lines)));
}

您需要require(utils)并安装curl,但不需要其他额外的软件包。


1
你可以使用format=tsv。在R中,需要使用read.delimdec = "," - Artem Klevtsov

0

感谢这个解决方案!它和旧的一样好用。我使用了另一个修复方法来消除第一行的空白。当你仅仅排除它时,当该行“解冻”时,你可能会意外删除一个有效的观察结果。函数中的额外指令将删除任何没有时间戳的行。

readSpreadsheet <- function(url, sheet = 1){
   library(httr)
   r <- GET(url)
   html <- content(r)
   sheets <- readHTMLTable(html, header=FALSE, stringsAsFactors=FALSE)
   df <- sheets[[sheet]]
   dfClean <- function(df){
    nms <- t(df[1,])
    names(df) <- nms
    df <- df[-1,-1] 
    df <- df[df[,1] != "",]   ## only select rows with time stamps
    row.names(df) <- seq(1,nrow(df))
    df
   }
   dfClean(df)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接