R 将参差不齐的数据帧收集到键值列中
我最近发现了如何使用I函数进行创建,但是很难将它们与tidyr、ggplot2和Hadleyverse的其余部分集成在一起。更具体地说,如何将包含命名向量的列收集到键值列中 假设我创建这样一个数据帧R 将参差不齐的数据帧收集到键值列中,r,dataframe,tidyr,R,Dataframe,Tidyr,我最近发现了如何使用I函数进行创建,但是很难将它们与tidyr、ggplot2和Hadleyverse的其余部分集成在一起。更具体地说,如何将包含命名向量的列收集到键值列中 假设我创建这样一个数据帧 make.vector <- function(length.out){ x <- sample(9, length.out) names(x) <- switch(length.out, "Alice", c("Bob", "Cha
make.vector <- function(length.out){
x <- sample(9, length.out)
names(x) <- switch(length.out,
"Alice",
c("Bob", "Charlie"),
c("Dave", "Erin", "Frank"),
c("Gwen", "Harold", "Inez", "James"))
x
}
mydf <- data.frame(Game = gl(3, 3, labels=LETTERS[1:3]),
Set = rep(1:3, 3),
Score = I(lapply(rep(2:4, each=3), make.vector)))
只要结果达到预期长度,就可以直接使用dplyr和tidyr操纵数据帧
mydf %>%
mutate(nPlayers = sapply(Score, length))
mydf %>%
group_by(Game) %>%
summarize(TotalScore = list(Reduce("+", Score)))
但是,我不知道如何为每个原始行创建多行结果。假设我想通过操纵mydf创建以下数据帧:
我所知道的唯一工具是tidyr包的gather函数,但它似乎不能很好地处理非原子数据
mydf %>%
mutate(Player = lapply(Score, names)) %>%
gather(P = Player, S = Score)
我想我可以像前面类似的问题一样,拼凑出一个解决方案
但我有一种感觉,如果下周回顾一下代码,我将很难消化它。有没有一个官方的或者至少是更聪明的方法来做到这一点?否则,我将为它创建一个通用函数,并将其添加到我的个人库中
使现代化
根据下面的说明,我发现dplyr也可以达到同样的效果
我会尝试使用data.table按组取消列表。每个组只能运行一次,同时使用花括号将其存储在临时变量中,就像在jth表达式的函数中一样
library(data.table)
setDT(mydf)[, {
temp <- unlist(Score)
.(Player = names(temp), Score = temp)
}, by = .(Game, Set)]
# Game Set Player Score
# 1: A 1 Bob 2
# 2: A 1 Charlie 9
# 3: A 2 Bob 6
# 4: A 2 Charlie 3
# 5: A 3 Bob 2
# 6: A 3 Charlie 8
# 7: B 1 Dave 1
# 8: B 1 Erin 6
# 9: B 1 Frank 5
# 10: B 2 Dave 3
#...
我会尝试使用data.table按组取消列表。每个组只能运行一次,同时使用花括号将其存储在临时变量中,就像在jth表达式的函数中一样
library(data.table)
setDT(mydf)[, {
temp <- unlist(Score)
.(Player = names(temp), Score = temp)
}, by = .(Game, Set)]
# Game Set Player Score
# 1: A 1 Bob 2
# 2: A 1 Charlie 9
# 3: A 2 Bob 6
# 4: A 2 Charlie 3
# 5: A 3 Bob 2
# 6: A 3 Charlie 8
# 7: B 1 Dave 1
# 8: B 1 Erin 6
# 9: B 1 Frank 5
# 10: B 2 Dave 3
#...
我会选择librarydata.table;setDTmydf[,{temp我认为这肯定是一个改进,但只是在`[.data.table`setDTmydf,{:找不到函数。当我尝试它时。也得到了最新版本的data.table.hmm..v1.9.4。根据文档。尝试将.to列表转换为setDTmydf[,,{temp谢谢,这对我很有用!这可能不是一个超级漂亮的解决方案,但它确实正确地处理了分组,并消除了cbind。我也不认为它有那么难看:我会使用librarydata.table;setDTmydf[,{temp我认为这肯定是一个改进,但只会在`[.data.table`setDTmydf中出错,{:找不到函数。当我尝试它时。也得到了data.table的最新版本。嗯..v1.9.4应该有。根据文档。尝试将.to列表转换为setDTmydf[,,{temp谢谢,这对我来说很有用!这可能不是一个超级漂亮的解决方案,但它确实正确地处理了分组并消除了cbind。尽管如此,我并不认为它有那么难看:
cbind(
mydf[rep(1:nrow(mydf), sapply(mydf$Score, length)),
c("Game", "Set")],
data.frame(
Player = unlist(lapply(mydf$Score, names)),
Score = unlist(mydf$Score)
)
)
mydf %>%
group_by(Game, Set) %>%
do(with(., data.frame(Player = names(unlist(Score)),
Score = unlist(Score))))
# Game Set Player Score
# 1 A 1 Bob 8
# 2 A 1 Charlie 6
# 3 A 2 Bob 7
# 4 A 2 Charlie 6
# 5 A 3 Bob 5
# 6 A 3 Charlie 8
# 7 B 1 Dave 1
# 8 B 1 Erin 9
# 9 B 1 Frank 3
# 10 B 2 Dave 8
# .. ... ... ... ...
# Warning message:
# In rbind_all(out[[1]]) : Unequal factor levels: coercing to character
library(data.table)
setDT(mydf)[, {
temp <- unlist(Score)
.(Player = names(temp), Score = temp)
}, by = .(Game, Set)]
# Game Set Player Score
# 1: A 1 Bob 2
# 2: A 1 Charlie 9
# 3: A 2 Bob 6
# 4: A 2 Charlie 3
# 5: A 3 Bob 2
# 6: A 3 Charlie 8
# 7: B 1 Dave 1
# 8: B 1 Erin 6
# 9: B 1 Frank 5
# 10: B 2 Dave 3
#...