高效且有选择地组合 R 中的列
Efficiently and selectively combining columns in R
我有以下数据
countrycols = alljson[,c("country_gc_str","country_ipapi_str","country_tm_str")]
head(countrycols)
country_gc_str country_ipapi_str country_tm_str
1 <NA> RU RU
2 <NA> CN CN
3 US US US
4 <NA> CD CG
5 <NA> DE DE
6 <NA> <NA> NG
我想创建一个新列 country_final_str,其中按以下优先顺序填充国家/地区数据:
country_gc_str
country_ipapi_str
country_tm_str
我还使用以下方法来描述国家收入水平:
wbURL <- "http://api.worldbank.org/countries?per_page=304"
xmlAPI <- xmlParse(wbURL)
xmlDF <- xmlToDataFrame(xmlAPI)
xmlDF$iso2CodeChar <- as.character(xmlDF$iso2Code)
xmlDF$incomeLevelChar <- as.character(xmlDF$incomeLevel)
incomexml <- xmlDF[,c("iso2CodeChar","incomeLevelChar")]
incomexmltable <- as.data.table(incomexml)
我有以下 for 循环,但它需要永远,因为我有超过一百万条记录:
alljson$country_final_str <- alljson$country_gc_str
alljson$income_level <- NA
for (i in 1:length (alljson$country_final_str))
{
if (is.na(alljson$country_final_str [i]))
{
alljson$country_final_str [i] = alljson$country_ipapi_str [i];
}
if (is.na(alljson$country_final_str [i]))
{
alljson$country_final_str [i] = alljson$country_tm_str [i];
}
a<-incomexmltable[iso2CodeChar==alljson$country_final_str [i]]$incomeLevelChar
if(length(a)==0)
{
alljson$income_level [i] <- NA
} else {
alljson$income_level [i] <- a
}
}
关于改进 efficiency/getting 摆脱 for 循环的任何想法?我想不出 apply/lapply/tapply
的方法,而且我在 Windows,所以我使用 doParallel
和 doSNOW
并行化我的代码的努力失败了。
请参阅下面@thelatemail 对专栏问题的正确答案。对于国家收入水平,我执行了:
allcountries <- unique(alljson$country_final_str)
alljson$country_income_str <- NA
sum(!is.na(countrycode(allcountries, "iso2c", "country.name")))
for (i in 1:length(allcountries))
{
a<-incomexmltable[iso2CodeChar==allcountries[i]]$incomeLevelChar
if(length(a)==0)
{
alljson$country_income_str[which(alljson$country_final_str==allcountries[i])] <- NA
} else {
alljson$country_income_str[which(alljson$country_final_str==allcountries[i])] <- a
}
alljson$country_income_str
}
下面是在三个变量中选取第一个非缺失值后使用矩阵索引的尝试:
countrycols[
cbind(
seq_len(nrow(countrycols)),
max.col(replace( -col(countrycols), is.na(countrycols), -Inf))
)
]
#[1] "RU" "CN" "US" "CD" "DE" "NG"
为了解释逻辑,分解每一行:
-col(countrycols)
# [,1] [,2] [,3]
#[1,] -1 -2 -3
#[2,] -1 -2 -3
#[3,] -1 -2 -3
#[4,] -1 -2 -3
#[5,] -1 -2 -3
#[6,] -1 -2 -3
replace( -col(countrycols), is.na(countrycols), -Inf)
# [,1] [,2] [,3]
#[1,] -Inf -2 -3
#[2,] -Inf -2 -3
#[3,] -1 -2 -3
#[4,] -Inf -2 -3
#[5,] -Inf -2 -3
#[6,] -Inf -Inf -3
(colindex <- max.col(replace( -col(countrycols), is.na(countrycols), -Inf)) )
#[1] 2 2 1 2 2 3
cbind(rowindex=seq_len(nrow(countrycols)), colindex)
# rowindex colindex
#[1,] 1 2
#[2,] 2 2
#[3,] 3 1
#[4,] 4 2
#[5,] 5 2
#[6,] 6 3
这个最终矩阵用于从原始列表中提取每个 row/col 组合的子集。
其中 countrycols
是:
structure(list(country_gc_str = c(NA, NA, "US", NA, NA, NA),
country_ipapi_str = c("RU", "CN", "US", "CD", "DE", NA),
country_tm_str = c("RU", "CN", "US", "CG", "DE", "NG")), .Names = c("country_gc_str",
"country_ipapi_str", "country_tm_str"), row.names = c("1", "2",
"3", "4", "5", "6"), class = "data.frame")
我有以下数据
countrycols = alljson[,c("country_gc_str","country_ipapi_str","country_tm_str")]
head(countrycols)
country_gc_str country_ipapi_str country_tm_str
1 <NA> RU RU
2 <NA> CN CN
3 US US US
4 <NA> CD CG
5 <NA> DE DE
6 <NA> <NA> NG
我想创建一个新列 country_final_str,其中按以下优先顺序填充国家/地区数据:
country_gc_str
country_ipapi_str
country_tm_str
我还使用以下方法来描述国家收入水平:
wbURL <- "http://api.worldbank.org/countries?per_page=304"
xmlAPI <- xmlParse(wbURL)
xmlDF <- xmlToDataFrame(xmlAPI)
xmlDF$iso2CodeChar <- as.character(xmlDF$iso2Code)
xmlDF$incomeLevelChar <- as.character(xmlDF$incomeLevel)
incomexml <- xmlDF[,c("iso2CodeChar","incomeLevelChar")]
incomexmltable <- as.data.table(incomexml)
我有以下 for 循环,但它需要永远,因为我有超过一百万条记录:
alljson$country_final_str <- alljson$country_gc_str
alljson$income_level <- NA
for (i in 1:length (alljson$country_final_str))
{
if (is.na(alljson$country_final_str [i]))
{
alljson$country_final_str [i] = alljson$country_ipapi_str [i];
}
if (is.na(alljson$country_final_str [i]))
{
alljson$country_final_str [i] = alljson$country_tm_str [i];
}
a<-incomexmltable[iso2CodeChar==alljson$country_final_str [i]]$incomeLevelChar
if(length(a)==0)
{
alljson$income_level [i] <- NA
} else {
alljson$income_level [i] <- a
}
}
关于改进 efficiency/getting 摆脱 for 循环的任何想法?我想不出 apply/lapply/tapply
的方法,而且我在 Windows,所以我使用 doParallel
和 doSNOW
并行化我的代码的努力失败了。
请参阅下面@thelatemail 对专栏问题的正确答案。对于国家收入水平,我执行了:
allcountries <- unique(alljson$country_final_str)
alljson$country_income_str <- NA
sum(!is.na(countrycode(allcountries, "iso2c", "country.name")))
for (i in 1:length(allcountries))
{
a<-incomexmltable[iso2CodeChar==allcountries[i]]$incomeLevelChar
if(length(a)==0)
{
alljson$country_income_str[which(alljson$country_final_str==allcountries[i])] <- NA
} else {
alljson$country_income_str[which(alljson$country_final_str==allcountries[i])] <- a
}
alljson$country_income_str
}
下面是在三个变量中选取第一个非缺失值后使用矩阵索引的尝试:
countrycols[
cbind(
seq_len(nrow(countrycols)),
max.col(replace( -col(countrycols), is.na(countrycols), -Inf))
)
]
#[1] "RU" "CN" "US" "CD" "DE" "NG"
为了解释逻辑,分解每一行:
-col(countrycols)
# [,1] [,2] [,3]
#[1,] -1 -2 -3
#[2,] -1 -2 -3
#[3,] -1 -2 -3
#[4,] -1 -2 -3
#[5,] -1 -2 -3
#[6,] -1 -2 -3
replace( -col(countrycols), is.na(countrycols), -Inf)
# [,1] [,2] [,3]
#[1,] -Inf -2 -3
#[2,] -Inf -2 -3
#[3,] -1 -2 -3
#[4,] -Inf -2 -3
#[5,] -Inf -2 -3
#[6,] -Inf -Inf -3
(colindex <- max.col(replace( -col(countrycols), is.na(countrycols), -Inf)) )
#[1] 2 2 1 2 2 3
cbind(rowindex=seq_len(nrow(countrycols)), colindex)
# rowindex colindex
#[1,] 1 2
#[2,] 2 2
#[3,] 3 1
#[4,] 4 2
#[5,] 5 2
#[6,] 6 3
这个最终矩阵用于从原始列表中提取每个 row/col 组合的子集。
其中 countrycols
是:
structure(list(country_gc_str = c(NA, NA, "US", NA, NA, NA),
country_ipapi_str = c("RU", "CN", "US", "CD", "DE", NA),
country_tm_str = c("RU", "CN", "US", "CG", "DE", "NG")), .Names = c("country_gc_str",
"country_ipapi_str", "country_tm_str"), row.names = c("1", "2",
"3", "4", "5", "6"), class = "data.frame")