我有一个“熔化的”数据帧df,其中有多个索引列和一个观察列。
这是一个“密集”数据帧。即在索引列中存在对值的每种组合的观察。而且,它是一对一的。即索引值的每个组合都对应一个观察值。
我正在尝试编写一种自动的方法,以将其转换为层次结构列表结构hl,以使列表的第n级名称对应于数据帧的第n列的唯一值以及然后列表就是数据框观察栏中的相应值。
例如
可以指定级别为“ n”的hl名称df[[colnames(df)[n]]]%>%unique()
然后的目标是使下面的示例工作而不必为每个单独的列显式构造一个for循环。 不需要手动构造循环很重要,因为先验地我不知道数据帧中将存在多少个索引列。 一个例子
require(dplyr)
tempA=rep(letters[1:3],9)
tempB=c(rep(mapply(function(x){rep(LETTERS[x],3)},c(1:3)),3))
tempC=c(mapply(function(x){rep(x,9)},c(1:3)))
tempObs=paste(tempA,tempB,tempC,sep="_")
df=data.frame(A=tempA,B=tempB,C=tempC,Obs=tempObs)
df
hl=list()
for(iA in df$A%>%unique){
hl[[iA]]=list()
for(iB in df$B%>%unique){
hl[[iA]][[iB]]=list()
for(iC in df$C%>%unique){
hl[[iA]][[iB]][[iC]]=(df%>%
filter(A==iA,B==iB,C==iC))$Obs[1]
}
}
}
hl
hl[['a']][['A']][[1]]
收益:
A B C Obs
a A 1 a_A_1
b A 1 b_A_1
c A 1 c_A_1
a B 1 a_B_1
b B 1 b_B_1
c B 1 c_B_1
a C 1 a_C_1
b C 1 b_C_1
c C 1 c_C_1
a A 2 a_A_2
b A 2 b_A_2
c A 2 c_A_2
a B 2 a_B_2
b B 2 b_B_2
c B 2 c_B_2
a C 2 a_C_2
b C 2 b_C_2
c C 2 c_C_2
a A 3 a_A_3
b A 3 b_A_3
c A 3 c_A_3
a B 3 a_B_3
b B 3 b_B_3
c B 3 c_B_3
a C 3 a_C_3
b C 3 b_C_3
c C 3 c_C_3
$a
$A
a_A_1
a_A_2
a_A_3
$B
a_B_1
a_B_2
a_B_3
$C
a_C_1
a_C_2
a_C_3
$b
$A
b_A_1
b_A_2
b_A_3
$B
b_B_1
b_B_2
b_B_3
$C
b_C_1
b_C_2
b_C_3
$c
$A
c_A_1
c_A_2
c_A_3
$B
c_B_1
c_B_2
c_B_3
$C
c_C_1
c_C_2
c_C_3
a_A_1
经过一番摸索,我可以使用递归得到一个幼稚的解决方案。但是,这对我来说似乎很不雅...
df_to_hl <- function(df,
indCols=(df%>%colnames)[c(1:(length(df%>%colnames)-1))],
iCol=1,vList=c()){
hl=list()
if(iCol<length(indCols)){
for(iVal in df[[indCols[iCol]]]%>%unique){
hl[[iVal]]=df_to_hl(df,indCols,iCol+1,vList=c(vList,iVal))
}
} else {
for(iVal in df[[indCols[iCol]]]%>%unique){
hl[[iVal]]=(df%>%filter_(paste(indCols,'==',shQuote(c(vList,iVal)),collapse="&")))[[last(df%>%colnames)]][1]
}
}
return(hl)
}