高效重塑大数据集
Efficiently reshaping big datasets
世界发展指标如下
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)
它过去工作没有任何问题,但由于某种原因,它现在需要太多内存才能完成操作。
我已经尝试从工作中删除所有其他数据库 space,gc()
,关闭计算机上的所有其他程序并减少用于重塑的年数,但这并没有解决问题。因此,我想知道是否有一种内存占用较少的方法来处理这个问题。
编辑 1:根据这个 post dcast.data.table
或 reshape
(因为不是 运行 内存不足)是要走的路。然而,我在重写语法时遇到了很多麻烦(我也得到了 dplyr 回答我发布的问题)我将如何重写 dplyr
代码以使用 dcast/reshape?
术语 select
、gather
、spread
与 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")
但后来我得到 "warning" Aggregation function missing: defaulting to length
并且所有条目都只是 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)
您还可以通过使用 gather
的 na.rm = TRUE
选项来避免一些中间尺寸 inflation,这可能会加快速度...
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)
为了获得更多解释,请注意如果您 "accidentally" 使用上面创建的示例数据集不在收集命令中包含 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)
世界发展指标如下
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)
它过去工作没有任何问题,但由于某种原因,它现在需要太多内存才能完成操作。
我已经尝试从工作中删除所有其他数据库 space,gc()
,关闭计算机上的所有其他程序并减少用于重塑的年数,但这并没有解决问题。因此,我想知道是否有一种内存占用较少的方法来处理这个问题。
编辑 1:根据这个 post dcast.data.table
或 reshape
(因为不是 运行 内存不足)是要走的路。然而,我在重写语法时遇到了很多麻烦(我也得到了 dplyr 回答我发布的问题)我将如何重写 dplyr
代码以使用 dcast/reshape?
术语 select
、gather
、spread
与 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")
但后来我得到 "warning" Aggregation function missing: defaulting to length
并且所有条目都只是 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)
您还可以通过使用 gather
的 na.rm = TRUE
选项来避免一些中间尺寸 inflation,这可能会加快速度...
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)
为了获得更多解释,请注意如果您 "accidentally" 使用上面创建的示例数据集不在收集命令中包含 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)