R:循环加入清单

时间:2018-12-18 04:31:22

标签: r list loops join

我正在尝试做一些非常简单的事情,但是我似乎没有成功,也没有找到解决这个特定问题的答案...

我只想在循环中加入列表。

检查我的MWE。

我有一个像这样的数据框:

set.seed(123)
mydf <- data.frame(letters=sample(LETTERS[1:4],20,replace=TRUE), numbers=sample(1:5,20,replace=TRUE))
mydf[] <- lapply(mydf, factor)
> mydf
   letters numbers
1        B       5
2        D       4
3        B       4
4        D       5
5        D       4
6        A       4
7        C       3
8        D       3
9        C       2
10       B       1
11       D       5
12       B       5
13       C       4
14       C       4
15       A       1
16       D       3
17       A       4
18       A       2
19       B       2
20       D       2

我从其中列出2个列表(每列一个),每个级别都有一个颜色,例如:

library(RColorBrewer)

cols1 <- colorRampPalette(brewer.pal(length(levels(mydf[,1])), "Set1"))
myPal1 <- cols1(length(levels(mydf[,1])))
myc1 <- list(myPal1)
names(myc1) <- names(mydf)[1]
names(myc1[[1]]) <- levels(mydf[,1])

cols2 <- colorRampPalette(brewer.pal(length(levels(mydf[,2])), "Set1"))
myPal2 <- cols2(length(levels(mydf[,2])))
myc2 <- list(myPal2)
names(myc2) <- names(mydf)[2]
names(myc2[[1]]) <- levels(mydf[,2])

并加入他们:

mycolors1 <- c(myc1, myc2)
> mycolors1
$letters
        A         B         C         D 
"#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" 

$numbers
        1         2         3         4         5 
"#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" "#FF7F00" 

mycolors1列表正是我想要的输出。

但是,如果我尝试在循环中执行完全相同的操作,则不会得到相同的结果:

mycolors2 <- list()
for (i in dim(mydf)[2]){
  cols <- colorRampPalette(brewer.pal(length(levels(mydf[,i])), "Set1"))
  myPal <- cols(length(levels(mydf[,i])))
  myc <- list(myPal)
  names(myc) <- names(mydf)[i]
  names(myc[[1]]) <- levels(mydf[,i])
  mycolors2 <- c(mycolors2, myc)
}
> mycolors2
$numbers
        1         2         3         4         5 
"#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" "#FF7F00" 

我在这里做错了什么?

如何获得与以前相同的输出,但是这次是在循环内?(使mycolors2 == {mycolors1)?

1 个答案:

答案 0 :(得分:1)

我一直很着迷于避免在R中使用for循环,而是从哈德利的purrr函数编程技术中汲取灵感。

set.seed(123)
mydf <- data_frame(letters=sample(LETTERS[1:4],20,replace=TRUE), 
numbers=sample(1:5,20,replace=TRUE))

我相信我已经清理了您的代码,所以我希望保留其原始功能。下面的输出让您知道是否是这种情况。

因此,您无需创建循环,而是创建一个使颜色成为矢量的函数:

uniqueElementsPalette <- function(myvec) {

  myvec <- as_tibble(myvec)

  myc <- myvec %>%
    unique() %>%
    nrow() %>%
    brewer.pal("Set1") %>%
    as_tibble()

  names(myc) <- names(myvec)

  return(myc)
}

让我们检查一下它是否有效:

> uniqueElementsPalette(mydf[,1])
# A tibble: 4 x 1
  letters
  <chr>  
1 #E41A1C
2 #377EB8
3 #4DAF4A
4 #984EA3

现在,只需使用apply,它就可以使用您的函数(最后一个参数)遍历数据帧中的每一列(即下面函数中的2)。

mypalettes <- apply(mydf, 2, uniqueElementsPalette)

结果:

> mypalettes
$`letters`
# A tibble: 4 x 1
  value  
  <chr>  
1 #E41A1C
2 #377EB8
3 #4DAF4A
4 #984EA3

$numbers
# A tibble: 5 x 1
  value  
  <chr>  
1 #E41A1C
2 #377EB8
3 #4DAF4A
4 #984EA3
5 #FF7F00