[英]rbind all data frames with common names based on list using lapply
我有幾個這樣命名的數據框:
orange_ABC
orange_BCD
apple_ABC
apple_BCD
grape_ABC
grape_BCD
我需要rbind
那些有他們的名字在普通(橘子,蘋果,葡萄)的第一部分,並命名新的數據幀這樣。 我正在從數據幀names(fruitlist)
列表names(fruitlist)
(從中制成上述數據幀)的列表中訪問名稱,並嘗試將lapply
與function(x)
配合使用而沒有運氣。 我對R有點陌生,所以在動態命名新數據框時,我想我犯了一個簡單的錯誤……
lapply(names(fruitlist),
function(x){
frame_nm <- toString((names(fruitlist[x])))
frame_nm <- do.call(rbind, mget(ls(pattern=paste0((names(splitlist[x])),"*"))))
})
我已經在一種類型的“水果”上嘗試了獨立生產線,但似乎行得通:
test_DF <- do.call(rbind, mget(ls(pattern="apple*")))
編輯:我意識到我忘了提到動態創建6個數據幀的示例列表,所以我不能簡單地生成它們的列表。 但是,我確實有一個“水果”列表,並且所有新數據幀名稱的所有可能結尾都是已知的(“ _ABC”和“ _BCD”)。
如果您的fruitlist
清單是數據幀的命名清單,則可能適合。
首先,將類似的名稱放入自己的列表中:
fruit.groups <- split(names(fruitlist),
sapply(strsplit(names(fruitlist), split = "_"), "[[", 1))
> fruit.groups
$apple
[1] "apple_ABC" "apple_BCD"
$grape
[1] "grape_ABC" "grape_BCD"
$orange
[1] "orange_ABC" "orange_BCD"
然后,使用lapply
到rbind
按組:
fdf <- lapply(fruit.groups, function(x){
out <- do.call(rbind, fruitlist[x])
out$from <- gsub("(\\..*)", "", rownames(out))
rownames(out) <- NULL
return(out)
})
> fdf$apple
a b from
1 1 11 apple_ABC
2 2 12 apple_ABC
3 3 13 apple_ABC
4 4 14 apple_ABC
5 1 11 apple_BCD
6 2 12 apple_BCD
7 3 13 apple_BCD
8 4 14 apple_BCD
偽數據:
namelist <- paste(fruit = rep(c("orange", "apple", "grape"), 2),
nums = rep(c("_ABC", "_BCD"), each = 3), sep = "")
fruitlist <- llply(namelist, function(x){
assign(as.character(x), data.frame(a = 1:4, b = 11:14))
})
編輯:
從上述修改到您的問題:
如果您有成果和后綴,請使用expand.grid
獲取所有可能的組合(假設所有組合都將引用動態生成的數據幀)。
fruits <- c("orange", "apple", "grape")
suffixes <- c("_ABC", "_BCD")
fullnames <- apply(expand.grid(fruits, suffixes), 1, paste, collapse = "")
使用該名稱列表,使用mget
生成當前數據幀的列表。
new_fruit_df_list <- mget(fullnames)
然后,上面的代碼應該起作用,在此處進行修改以反映名稱更改:
fruit.groups <- split(names(new_fruit_df_list),
sapply(strsplit(names(new_fruit_df_list), split = "_"), "[[", 1))
fdf <- lapply(fruit.groups, function(x){
out <- do.call(rbind, new_fruit_df_list[x])
out$from <- gsub("(\\..*)", "", rownames(out))
rownames(out) <- NULL
return(out)
})
看看每列的開頭,添加的列(如果不需要的話刪除)顯示該行的原始數據框的名稱。
> lapply(fdf, head, 2)
$apple
a b from
1 1 11 apple_ABC
2 2 12 apple_ABC
$grape
a b from
1 1 11 grape_ABC
2 2 12 grape_ABC
$orange
a b from
1 1 11 orange_ABC
2 2 12 orange_ABC
令人懷疑的是,為對象分配值的建議方法不起作用。 此外,在使用ls()
和mget()
來列出和訪問函數中的命名對象時,必須mget()
小心,因為除非它們另有說明,否則它們不會自動升至父級環境並且僅在本地范圍內“查看”變量。 這適用於R版本3.4,舊版本的行為可能有所不同。
創建命名對象。
為了在全局環境中創建新對象,請使用assign()
(已在盧克C的答案中建議):
> assign("foo", "some text") > foo [1] "some text"
將代碼放在函數內部會引起局部作用域。 明確指定全局環境允許設置全局變量:
> set_foo <- function (x) { assign("foo", x, envir=globalenv()) } > set_foo("other text") > foo [1] "other text"
請注意,省略envir
參數將使全局環境不受影響。
在局部函數中使用ls()
/ mget()
。
默認情況下,它僅列出該函數的當前(本地)環境中的名稱,該名稱僅在問題中給出的示例代碼中看到參數x
。 與上述類似,一種快速解決方案是通過添加參數envir=globalenv()
顯式指定全局環境。 同樣適用於mget()
。
由於未提供MWE,因此我願意修改Luke C的答案中提供的“偽數據”示例代碼。
# Populate environment
namelist <- paste(fruit = rep(c("orange", "apple", "grape"), 2),
nums = rep(c("_ABC", "_BCD"), each = 3), sep = "")
for(x in namelist)
assign(x, data.frame(a = 1:4, b = 11:14))
# The following re-generates the list of fruits used above
grouplist <- unique(unlist(lapply(strsplit(namelist, "_"), function (x) { x[[1]] })))
# Group and rbind by prefix, suppressing output
invisible(lapply(grouplist,
function(x) {
grouped <- do.call(rbind,
mget(ls(pattern=paste0(x,"_*"), envir=globalenv()),
envir=globalenv()))
assign(x, grouped, envir=globalenv())
}))
試試看:
file_groups <- ls()[grep(".*_.*", ls())]
file_groups <- gsub("(.*)_.*", "\\1", file_groups)
df_list <- lapply(file_groups,
function(x){ do.call(rbind, mget(ls(pattern = paste0(x, "*"))))})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.