[英]How to convert DataFrames to nested lists
提供以下data.frame()
結構
var1.gender
var1.score.raw
var1.score.raw.lower
var1.score.raw.upper
[...]
var2.gender
var2.score.raw
var2.score.raw.lower
var2.score.raw.upper
[...]
我如何將其轉換為多維列表,除以.
?
樣本數據:
df <- data.frame('var1.gender' = c(1,1,3,3), 'var1.score.raw' = c(12.3, 12.4, 14.5, 13.2), 'var1.score.raw.lower' = c(11,11,13,12), 'var1.score.raw.upper' = c(13,13,15,14), 'var2.gender' = c(1,1,3,3), 'var2.score.raw' = c(12.3, 12.4, 14.5, 13.2), 'var2.score.raw.lower' = c(11,11,13,12), 'var2.score.raw.upper' = c(13,13,15,14))
結果列表應如下所示:
$var1
$var1$gender
[1] 1 1 3 3
$var1$score
$var1$score$raw
[1] 12.3 12.4 14.5 13.2
$var1$score$lower
[1] 11 11 13 12
$var1$score$upper
[1] 13 13 15 14
$var2
$var2$gender
[1] 1 1 3 3
$var2$score
$var2$score$raw
[1] 12.3 12.4 14.5 13.2
$var2$score$lower
[1] 11 11 13 12
$var2$score$upper
[1] 13 13 15 14
通過構建“ df”的方式,一種構建通緝名單的簡單方法是評估像list[["X"]][["Y"]][["Z"]][...] = df$XYZ..
這樣的調用list[["X"]][["Y"]][["Z"]][...] = df$XYZ..
對於“ df”的每一列。 這可以通過操縱“語言”對象來動態完成。
定義一個接受列表的函數,名稱/索引的字符向量以及在該級別要分配的值,我們有:
assign_list_element = function(x, inds, val)
{
cl = bquote(x[[.(inds[1])]])
for(s in inds[-1]) cl = bquote(.(cl)[[.(s)]])
cl = call("<-", cl, bquote(.(val)))
print(cl); flush.console()
eval(cl)
return(x)
}
某些bquote
調用可以變得更簡單,也可以由bquote
substitute
,但是,按上述方式使用它可以構造有關索引的更好格式的調用(出於打印目的)。
然后,對於“ df”的每一列,重新組織一個-at start empty-list:
nms = strsplit(names(df), ".", TRUE)
l = list()
for(i in seq_along(nms)) l = assign_list_element(l, nms[[i]], df[[i]])
#x[["var1"]][["gender"]] <- c(1, 1, 3, 3)
#x[["var1"]][["score"]][["raw"]] <- c(12.3, 12.4, 14.5, 13.2)
#x[["var1"]][["score"]][["lower"]] <- c(11, 11, 13, 12)
#x[["var1"]][["score"]][["upper"]] <- c(13, 13, 15, 14)
#x[["var2"]][["gender"]] <- c(1, 1, 3, 3)
#x[["var2"]][["score"]][["raw"]] <- c(12.3, 12.4, 14.5, 13.2)
#x[["var2"]][["score"]][["lower"]] <- c(11, 11, 13, 12)
#x[["var2"]][["score"]][["upper"]] <- c(13, 13, 15, 14)
str(l)
#List of 2
# $ var1:List of 2
# ..$ gender: num [1:4] 1 1 3 3
# ..$ score :List of 3
# .. ..$ raw : num [1:4] 12.3 12.4 14.5 13.2
# .. ..$ lower: num [1:4] 11 11 13 12
# .. ..$ upper: num [1:4] 13 13 15 14
# $ var2:List of 2
# ..$ gender: num [1:4] 1 1 3 3
# ..$ score :List of 3
# .. ..$ raw : num [1:4] 12.3 12.4 14.5 13.2
# .. ..$ lower: num [1:4] 11 11 13 12
# .. ..$ upper: num [1:4] 13 13 15 14
使用這種方法,盡管沒有復制其元素,但列表在每次迭代時都會重新構建。
我將在稍后編輯此內容,以查看列名中的句點(要復雜得多),但是如果不進行自動化,則可以創建嵌套列表,如下所示:
df <- data.frame('var1.gender' = c(1,1,3,3), 'var1.score.raw' = c(12.3, 12.4, 14.5, 13.2), 'var1.score.raw.lower' = c(11,11,13,12), 'var1.score.raw.upper' = c(13,13,15,14), 'var2.gender' = c(1,1,3,3), 'var2.score.raw' = c(12.3, 12.4, 14.5, 13.2), 'var2.score.raw.lower' = c(11,11,13,12), 'var2.score.raw.upper' = c(13,13,15,14))
df
# changed your naming here to remove the not-needed ".raw."
colnames(df) <- c("var1.gender", "var1.score.raw", "var1.score.lower", "var1.score.upper", "var2.gender", "var2.score.raw", "var2.score.lower", "var2.score.upper")
nested <- with(df, expr = {list(var1 = list(gender = var1.gender,
score = list(raw = var1.score.raw,
lower = var1.score.lower,
upper = var1.score.upper)),
var2 = list(gender = var2.gender,
score = list(raw = var2.score.raw,
lower = var2.score.lower,
upper = var2.score.upper)))})
nested
$var1
$var1$gender
[1] 1 1 3 3
$var1$score
$var1$score$raw
[1] 12.3 12.4 14.5 13.2
$var1$score$lower
[1] 11 11 13 12
$var1$score$upper
[1] 13 13 15 14
$var2
$var2$gender
[1] 1 1 3 3
$var2$score
$var2$score$raw
[1] 12.3 12.4 14.5 13.2
$var2$score$lower
[1] 11 11 13 12
$var2$score$upper
[1] 13 13 15 14
試圖為此做一個動態的版本,但迷路了遞歸。 無論如何,如果您擴展數據集中的varX數量,這可能會起作用。 它不像手工操作那么干凈,仍然有一個空列表。
nester <- function(df, splitby = "."){
separated <- strsplit(colnames(df), paste0("[", splitby, "]"))
# in order to rbind this into a matrix, we have to make all vectors the same length
n <- max(rapply(separated, length))
separated <- do.call(rbind, rapply(separated, function(x) {length(x) <- n; x }, how = "replace"))
separated <- ifelse(is.na(separated), "empty", separated)
listnames <- apply(separated, 2, unique)
L <- list()
# Assumes n is 3.
for(L1 in listnames[[1]]){
L[[L1]] <- list() # create List level 1
for(L2 in listnames[[2]]){
L[[L1]][[L2]] <- list() # create List level 2
for(L3 in listnames[[3]]){
L[[L1]][[L2]][[L3]] <- list() # create list level 3
# If no data exists for that list combination ...
if(length(df[,which(separated[,1] == L1 & separated[,2] == L2 & separated[,3] == L3)]) == 0){
L[[L1]][[L2]][[L3]] <- NULL # then remove that nested list.
} else {
# otherwise go ahead and put that column in as a list
L[[L1]][[L2]][[L3]] <- df[,which(separated[,1] == L1 & separated[,2] == L2 & separated[,3] == L3)]
# if data is sitting in a list$empty ...
if( L3 == "empty" ){
z <- unname(unlist(L[[L1]][[L2]][[L3]]))
L[[L1]][[L2]][[L3]] <- as.vector(z) # save the empty L3 to the L2
#L[[L1]][[L2]][[L3]] <- NULL # and delete the L3
}
}
}
}
}
return(L)
}
df.List <- nester(df, splitby = ".")
df.List
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.