我试图将列拆分为多个拆分数据框中的行名,然后在所有数据框中应用一个函数? (长度不等)我得到了下面的代码中嵌入的错误。我可以解决这个问题吗?
# sample dataset below
ID <- c("SB1","SB2","SB3","SB4","SB1","SB1","SB2","SB4","SB2", "SB1")
z <- c("A","B","C","D","E","A","B","C","D","D")
x <- 1:2
y <- 1:10
n <- max(length(x), length(y))
year <- c(1999,1999,1999,1999,2000,2001,2000,2001,2001,2002)
length(x) <- n
length(y) <- n
length(z) <- n
length(year) <- n
sitebyspec <- cbind(ID,x,y,z,year)
sitebyspec <- as.data.frame(sitebyspec)
# my process (split df by year, force ID column to rownames)
sitebyspec.split <- split(sitebyspec, (sitebyspec$year)) # split based on season
as.data.frame(sitebyspec.split) %>% remove_rownames %>% column_to_rownames(var="ID")
## Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, : arguments imply differing number of rows: 4, 2, 3, 1
# my next step if this worked ...
sitebyspec.split %>%
sitebyspec.split[,c(1:3)] %>%
map(~ contribdiv(., "richness")) %>%
map(summary)
能否将列名与行名集成到最后一步?
答案 0 :(得分:3)
使用修改后的数据(见下文),这是一个解决方案。
可能的主要问题在于您的数据。按照规定,您的x
列中有很多NA,我假设x
应该已经回收了。然后vegan::contribdiv()
至少需要两个维度,并且您只在数据中提供一行。此外,它需要数字,并且只能应用于列1:2
。在使用as.data.frame(sitebyspec.split)
的代码中,您试图将一个列表变成一个数据框,我认为这不是您想要的,并且会导致错误。
首先,使用lapply()
将ID
列转换为行名。
sitebyspec.split <- lapply(sitebyspec.split, function(x) "rownames<-"(x, x[, 1])[, -1])
第二,使用lapply()
将函数应用于列表。
library(vegan)
sitebyspec.result <- lapply(sitebyspec.split, function(x) contribdiv(x[, 1:2], "richness"))
结果
> sitebyspec.result
$`1999`
alpha beta gamma
SB1 0.6666667 0 0.6666667
SB2 0.6666667 0 0.6666667
SB3 0.6666667 0 0.6666667
$`2000`
alpha beta gamma
SB4 1 0 1
SB1 1 0 1
$`2001`
alpha beta gamma
SB1 0.6666667 0 0.6666667
SB2 0.6666667 0 0.6666667
SB4 0.6666667 0 0.6666667
$`2002`
alpha beta gamma
SB2 1 0 1
SB1 1 0 1
数据
sitebyspec <- data.frame(ID=c("SB1", "SB2", "SB3", "SB4", "SB1", "SB1", "SB2", "SB4", "SB2", "SB1"),
x=1:2,
y=1:10,
z=c("A", "B", "C", "D", "E", "A", "B", "C", "D", "D"),
year=c(1999, 1999, 1999, 2000, 2001, 2000, 2001, 2001, 2002, 2002))
答案 1 :(得分:1)
由于对象是std::allocate_shared()
,因此我们可以使用list
遍历list
,然后在OP的帖子中应用这些功能
map
sitebyspec.split %>%
map(~ .x %>%
remove_rownames %>%
column_to_rownames(var = "ID"))
#$`1999`
# x y z year
#SB1 1 1 A 1999
#SB2 2 2 B 1999
#SB3 1 3 C 1999
#$`2000`
# x y z year
#SB4 2 4 D 2000
#SB1 2 6 A 2000
#$`2001`
# x y z year
#SB1 1 5 E 2001
#SB2 1 7 B 2001
#SB4 2 8 C 2001
#$`2002`
# x y z year
#SB2 1 9 D 2002
#SB1 2 10 D 2002
函数可以在同一链中应用
contribdv
注意:OP将{x1,'y'列创建为library(vegan)
sitebyspec.split %>%
map(~ .x %>%
remove_rownames %>%
column_to_rownames(var = "ID") %>%
select(1:2) %>%
contribdiv(., "richness"))
#$`1999`
# alpha beta gamma
#SB1 0.6666667 0 0.6666667
#SB2 0.6666667 0 0.6666667
#SB3 0.6666667 0 0.6666667
#$`2000`
# alpha beta gamma
#SB4 1 0 1
#SB1 1 0 1
#$`2001`
# alpha beta gamma
#SB1 0.6666667 0 0.6666667
#SB2 0.6666667 0 0.6666667
#SB4 0.6666667 0 0.6666667
#$`2002`
# alpha beta gamma
#SB2 1 0 1
#SB1 1 0 1
,而应该是factor
numeric
答案 2 :(得分:1)
考虑基数R的by
。与split
不同,您可以直接在子集数据帧上传递函数:
proc_df <- function(df) df %>% remove_rownames %>% column_to_rownames(var="ID")
df_list <- by(sitebyspec, sitebyspec$year, proc_df)
df_list
# sitebyspec$year: 1999
# x y z year
# SB1 1 1 A 1999
# SB2 2 2 B 1999
# SB3 1 3 C 1999
# SB4 2 4 D 1999
# ----------------------------------------------------------------------------
# sitebyspec$year: 2000
# x y z year
# SB1 1 5 E 2000
# SB2 1 7 B 2000
# ----------------------------------------------------------------------------
# sitebyspec$year: 2001
# x y z year
# SB1 2 6 A 2001
# SB4 2 8 C 2001
# SB2 1 9 D 2001
# ----------------------------------------------------------------------------
# sitebyspec$year: 2002
# x y z year
# SB1 2 10 D 2002
对于扩展功能,
proc_df <- function(df) {
tryCatch({df %>%
remove_rownames %>%
column_to_rownames(var="ID") %>%
select(1:2) %>%
contribdiv(., "richness")
}, error = function(e) NA)
}
df_list <- by(sitebyspec, sitebyspec$year, proc_df)