【问题标题】:Efficiently reshaping big datasets有效地重塑大数据集
【发布时间】:2019-11-17 19:10:48
【问题描述】:

世界发展指标如下

library(data.table)
WDI <- fread("CountryName   CountryCode IndicatorName   IndicatorCode   1960    1961    2017
ArabWorld   ARB A   FX.OWN.TOTL.ZS  37.16521072 37.16521072 37.16521072
ArabWorld   ARB B   FX.OWN.TOTL.FE.ZS   25.63540268 25.63540268 25.63540268
ArabWorld   ARB C   FX.OWN.TOTL.MA.ZS   48.32851791 48.32851791 48.32851791
ArabWorld   ARB D   FX.OWN.TOTL.OL.ZS   42.54204559 42.54204559 42.54204559
ArabWorld   ARB E   FX.OWN.TOTL.40.ZS   27.72478104 27.72478104 27.72478104
ArabWorld   ARB F   FX.OWN.TOTL.PL.ZS   26.45811081 26.45811081 26.45811081
ArabWorld   ARB G   FX.OWN.TOTL.60.ZS   43.44695282 43.44695282 43.44695282
ArabWorld   ARB H   FX.OWN.TOTL.SO.ZS   48.66697693 48.66697693 48.66697693
ArabWorld   ARB I   FX.OWN.TOTL.YG.ZS   20.95479965 20.95479965 20.95479965
", header = TRUE)

我使用以下代码重塑了世界银行的世界发展指标数据库。

library(dplyr)
library(tidyr)

WDI <- WDI %>% 
  select(-`Indicator Name`) %>% 
  gather(Year, val,`1960`:`2017`) %>% 
  spread(`Indicator Code`, val)

它过去可以正常工作,但由于某种原因,它现在需要太多内存才能完成操作。

我试图从工作空间中删除所有其他数据库gc(),关闭计算机上的所有其他程序并减少用于重塑的年限,但这并没有解决问题。因此,我想知道是否有一种内存占用较少的方法来处理这个问题。


编辑1:根据这个postdcast.data.tablereshape(因为没有耗尽内存)是要走的路。然而,我在重写语法时遇到了很多麻烦(我也得到了 dplyr 回答我发布的问题)我将如何重写 dplyr 代码以使用 dcast/reshape?

selectgatherspread 这些术语与 dcast 和 reshape 有什么关系?


编辑 2:我首先尝试将 data.table 融化如下:

WDI = melt(WDI, id.vars = c("IndicatorCode", "CountryName", "CountryCode"),
               #  measure.vars = -c("IndicatorCode", "CountryName", "CountryCode", "IndicatorName"))
                measure.vars = c("1960", "1961","2017"))
colnames(WDI)[4] <- "year"
WDI = dcast(WDI, CountryName + CountryCode + year ~ IndicatorCode, value.var="value")

但随后我收到“警告”Aggregation function missing: defaulting to length,所有条目都只是 1 而不是值。当条目的组合不是唯一的时,这显然会发生。然而,我很确定它们是(国家和指标的组合,应该使条目独一无二)。

【问题讨论】:

  • 请帮助澄清您在所引用的帖子和将其应用于您的数据集之间的理解差距是什么
  • 我无法将您的数据读入 7 列。请让您的示例可重现。
  • 试试 dcast(melt(WDI, id = c(1:2, 4), measure = patterns("\\d+")), ... ~ IndicatorCode) 之类的。或者,如果它更易于阅读,您可以使用管道:melt(WDI, id = c(1:2, 4), measure = patterns("\\d+")) %&gt;% dcast(., ... ~ IndicatorCode)
  • melt 部分与您所做的完全一样,我只是使用了两个快捷方式:首先,我使用了列位置而不是它们的名称。其次,我使用了patterns(参见?patterns)函数来一次获取我想要测量的所有列(\\d+ 只是一个惰性正则表达式,用于获取带有数字标题的列)。在dcast 中,我也做了与您的尝试非常相似的事情,但还有另一个快捷方式-... 仅表示“获取所有列”。 data.table 本身表明它需要使用 value 作为聚合列。你真的不需要所有这些快捷方式——我只是懒惰。

标签: r dplyr reshape tidyr


【解决方案1】:

WDI 数据集不是特别大,所以我怀疑您的 gather 命令排除了每行唯一的列,从而导致大量重复,例如像2018 这样的额外年份列。

您可以更明确地使用 select 命令来避免这种情况,方法是只积极选择您需要的列,而不是消极地排除特定列,就像这样...

library(readr)
library(dplyr)
library(tidyr)

url <- "http://databank.worldbank.org/data/download/WDI_csv.zip"
zippath <- tempfile(fileext = ".zip")
download.file(url, zippath)

csvpath <- unzip(zippath, files = "WDIData.csv", exdir = tempdir())

WDI <- readr::read_csv(csvpath)

WDI %>% 
  select(`Country Name`, `Country Code`, `Indicator Code`, `1960`:`2017`) %>% 
  gather(Year, val,`1960`:`2017`) %>% 
  spread(`Indicator Code`, val)

或者您可以确保排除在重塑中不需要的列,就像这样...

library(readr)
library(dplyr)
library(tidyr)

url <- "http://databank.worldbank.org/data/download/WDI_csv.zip"
zippath <- tempfile(fileext = ".zip")
download.file(url, zippath)

csvpath <- unzip(zippath, files = "WDIData.csv", exdir = tempdir())

WDI <- readr::read_csv(csvpath)

WDI %>% 
  select(-`Indicator Name`, -`2018`, -`X64`) %>% 
  gather(Year, val,`1960`:`2017`) %>% 
  spread(`Indicator Code`, val)

您还可以通过使用gatherna.rm = TRUE 选项来避免一些中等规模的膨胀,这可能会加快速度...

library(readr)
library(dplyr)
library(tidyr)

url <- "http://databank.worldbank.org/data/download/WDI_csv.zip"
zippath <- tempfile(fileext = ".zip")
download.file(url, zippath)

csvpath <- unzip(zippath, files = "WDIData.csv", exdir = tempdir())

WDI <- readr::read_csv(csvpath)

WDI %>% 
  select(-`Indicator Name`, -`2018`, -`X64`) %>% 
  gather(Year, val,`1960`:`2017`, na.rm = TRUE) %>% 
  spread(`Indicator Code`, val)

如果需要更多解释,请注意如果您使用上面创建的示例数据集“不小心”在收集命令中不包含 2017 会发生什么...

library(data.table)
WDI <- fread("CountryName   CountryCode IndicatorName   IndicatorCode   1960    1961    2017
ArabWorld   ARB A   FX.OWN.TOTL.ZS  37.16521072 37.16521072 37.16521072
ArabWorld   ARB B   FX.OWN.TOTL.FE.ZS   25.63540268 25.63540268 25.63540268
ArabWorld   ARB C   FX.OWN.TOTL.MA.ZS   48.32851791 48.32851791 48.32851791
ArabWorld   ARB D   FX.OWN.TOTL.OL.ZS   42.54204559 42.54204559 42.54204559
ArabWorld   ARB E   FX.OWN.TOTL.40.ZS   27.72478104 27.72478104 27.72478104
ArabWorld   ARB F   FX.OWN.TOTL.PL.ZS   26.45811081 26.45811081 26.45811081
ArabWorld   ARB G   FX.OWN.TOTL.60.ZS   43.44695282 43.44695282 43.44695282
ArabWorld   ARB H   FX.OWN.TOTL.SO.ZS   48.66697693 48.66697693 48.66697693
ArabWorld   ARB I   FX.OWN.TOTL.YG.ZS   20.95479965 20.95479965 20.95479965
", header = TRUE)

library(dplyr)
library(tidyr)

WDI %>% 
  select(-`IndicatorName`) %>% 
  gather(Year, val,`1960`:`1961`) %>% 
  spread(`IndicatorCode`, val)

【讨论】:

  • 非常好!还增加了显示如何自动下载文件。
猜你喜欢
  • 1970-01-01
  • 2018-04-08
  • 2016-10-15
  • 2021-03-05
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 2013-07-21
相关资源
最近更新 更多