How can I plot a tree (and squirrels) in R?

后端 未结 5 1027
悲&欢浪女
悲&欢浪女 2020-12-24 06:32

Here is my tree:

tree = data.frame(branchID = c(1,11,12,111,112,1121,1122), length = c(32, 21, 19, 5, 12, 6, 2))

> tree
  branchID length
1        1              


        
5条回答
  •  感动是毒
    2020-12-24 06:47

    I probably over-thought this, but... squirrels.

    get.coords <- function(a, d, x0, y0) {
      a <- ifelse(a <= 90, 90 - a, 450 - a)
      data.frame(x = x0 + d * cos(a / 180 * pi), 
                 y = y0+ d * sin(a / 180 * pi))
    }
    
    
    tree$angle <- sapply(gsub(2, '+45', gsub(1, '-45', tree$branchID)), 
                         function(x) eval(parse(text=x)))
    tree$tipy <- tree$tipx <- tree$basey <- tree$basex <- NA
    
    for(i in seq_len(nrow(tree))) {
      if(tree$branchID[i] == 0) {
        tree$basex[i] <- tree$basey[i] <- tree$tipx[i] <- 0
        tree$tipy[i] <- tree$length[i]
        next
      } else if(tree$branchID[i] %in% 1:2) {
        parent <- 0
      } else {
        parent <- substr(tree$branchID[i], 1, nchar(tree$branchID[i])-1)
      }
      tree$basex[i] <- tree$tipx[which(tree$branchID==parent)]
      tree$basey[i] <- tree$tipy[which(tree$branchID==parent)]
      tip <- get.coords(tree$angle[i], tree$length[i], tree$basex[i], tree$basey[i])
      tree$tipx[i] <- tip[, 1]
      tree$tipy[i] <- tip[, 2]
    }  
    
    squirrels$nesty <- squirrels$nestx <- NA
    for (i in seq_len(nrow(squirrels))) {
      b <- tree[tree$branchID == squirrels$branchID[i], ]
      nest <- get.coords(b$angle, squirrels$PositionOnBranch[i], b$basex, b$basey)
      squirrels$nestx[i] <- nest[1]
      squirrels$nesty[i] <- nest[2]
    }
    

    And now we plot.

    plot.new()
    plot.window(xlim=range(tree$basex, tree$tipx), 
                ylim=range(tree$basey, tree$tipy), asp=1)
    with(tree, segments(basex, basey, tipx, tipy, lwd=pmax(10/nchar(branchID), 1)))
    points(squirrels[, c('nestx', 'nesty')], pch=21, cex=3, bg='white', lwd=2)
    text(squirrels[, c('nestx', 'nesty')], labels=seq_len(nrow(squirrels)), font=2)
    legend('bottomleft', legend=paste(seq_len(nrow(squirrels)), squirrels$name), bty='n')
    

    squizzerl

    And for kicks we will simulate a bigger tree (and put some apples on it like in Farmville):

    twigs <- replicate(50, paste(rbinom(5, 1, 0.5) + 1, collapse=''))
    branches <- sort(unique(c(sapply(twigs, function(x) sapply(seq_len(nchar(x)), function(y) substr(x, 1, y))))))
    tree <- data.frame(branchID=c(0, branches), length=c(30, sample(10, length(branches), TRUE)), 
                       stringsAsFactors=FALSE)
    
    
    tree$angle <- sapply(gsub(2, '+45', gsub(1, '-45', tree$branchID)), 
                         function(x) eval(parse(text=x)))
    tree$tipy <- tree$tipx <- tree$basey <- tree$basex <- NA
    
    for(i in seq_len(nrow(tree))) {
      if(tree$branchID[i] == 0) {
        tree$basex[i] <- tree$basey[i] <- tree$tipx[i] <- 0
        tree$tipy[i] <- tree$length[i]
        next
      } else if(tree$branchID[i] %in% 1:2) {
        parent <- 0
      } else {
        parent <- substr(tree$branchID[i], 1, nchar(tree$branchID[i])-1)
      }
      tree$basex[i] <- tree$tipx[which(tree$branchID==parent)]
      tree$basey[i] <- tree$tipy[which(tree$branchID==parent)]
      tip <- get.coords(tree$angle[i], tree$length[i], tree$basex[i], tree$basey[i])
      tree$tipx[i] <- tip[, 1]
      tree$tipy[i] <- tip[, 2]
    }  
    
    plot.new()
    plot.window(xlim=range(tree$basex, tree$tipx), 
                ylim=range(tree$basey, tree$tipy), asp=1)
    par(mar=c(0, 0, 0, 0))
    with(tree, segments(basex, basey, tipx, tipy, lwd=pmax(20/nchar(branchID), 1)))
    
    apple_branches <- sample(branches, 10)
    sapply(apple_branches, function(x) {
      b <- tree[tree$branchID == x, ]
      apples <- get.coords(b$angle, runif(sample(2, 1), 0, b$length), b$basex, b$basey)
      points(apples, pch=20, col='tomato2', cex=2)
    })
    

    enter image description here

提交回复
热议问题