Пакет Riverplot в R - участок вывода, покрытый линиями или контурами сетки

Я сделал диаграмму Санки в R Riverplot (v0.5), вывод выглядит ОК маленьким в RStudio, но при экспорте или увеличении в нем цвета имеют темные контуры или линии сетки.

The Riverplot image linked here shows the problem

Я думаю, это может быть потому, что контуры фигур не соответствуют прозрачности, которую я хочу использовать для заполнения?

Мне, возможно, нужно найти способ полностью избавиться от контуров (а не сделать их полупрозрачными), так как я думаю, что они также являются причиной того, что потоки со значением нуля все еще отображаются как тонкие линии.

мой код находится здесь:

#loading packages
library(readr)
library("riverplot", lib.loc="C:/Program Files/R/R-3.3.2/library")
library(RColorBrewer)

#loaing data
Cambs_flows <- read_csv("~/RProjects/Cambs_flows4.csv")

#defining the edges
edges = rep(Cambs_flows, col.names = c("N1","N2","Value"))
edges    <- data.frame(edges)
edges$ID <- 1:25

#defining the nodes
nodes <- data.frame(ID = c("Cambridge","S Cambs","Rest of E","Rest of UK","Abroad","to Cambridge","to S Cambs","to Rest of E","to Rest of UK","to Abroad"))
nodes$x = c(1,1,1,1,1,2,2,2,2,2)
nodes$y = c(1,2,3,4,5,1,2,3,4,5)

#picking colours
palette = paste0(brewer.pal(5, "Set1"), "90")

#plot styles
styles = lapply(nodes$y, function(n) {
  list(col = palette[n], lty = 0, textcol = "black")
})

#matching nodes to names
names(styles) = nodes$ID

#defining the river
r <- makeRiver( nodes, edges,
                node_labels = c("Cambridge","S Cambs","Rest of E","Rest of UK","Abroad","to Cambridge","to S Cambs","to Rest of E","to Rest of UK","to Abroad"),
                node_styles = styles)

#Plotting
plot( r, plot_area = 0.9)

И мои данные здесь

dput(Cambs_flows)
structure(list(N1 = c("Cambridge", "Cambridge", "Cambridge", 
"Cambridge", "Cambridge", "S Cambs", "S Cambs", "S Cambs", "S Cambs", 
"S Cambs", "Rest of E", "Rest of E", "Rest of E", "Rest of E", 
"Rest of E", "Rest of UK", "Rest of UK", "Rest of UK", "Rest of UK", 
"Rest of UK", "Abroad", "Abroad", "Abroad", "Abroad", "Abroad"
), N2 = c("to Cambridge", "to S Cambs", "to Rest of E", "to Rest of UK", 
"to Abroad", "to Cambridge", "to S Cambs", "to Rest of E", "to Rest of UK", 
"to Abroad", "to Cambridge", "to S Cambs", "to Rest of E", "to Rest of UK", 
"to Abroad", "to Cambridge", "to S Cambs", "to Rest of E", "to Rest of UK", 
"to Abroad", "to Cambridge", "to S Cambs", "to Rest of E", "to Rest of UK", 
"to Abroad"), Value = c(0L, 1616L, 2779L, 13500L, 5670L, 2593L, 
0L, 2975L, 4742L, 1641L, 2555L, 3433L, 0L, 0L, 0L, 6981L, 3802L, 
0L, 0L, 0L, 5670L, 1641L, 0L, 0L, 0L)), class = c("tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -25L), .Names = c("N1", "N2", 
"Value"), spec = structure(list(cols = structure(list(N1 = structure(list(), class = c("collector_character", 
"collector")), N2 = structure(list(), class = c("collector_character", 
"collector")), Value = structure(list(), class = c("collector_integer", 
"collector"))), .Names = c("N1", "N2", "Value")), default = structure(list(), class = c("collector_guess", 
"collector"))), .Names = c("cols", "default"), class = "col_spec"))

Ответ 1

Преступник - это строка в riverplot::curveseg. Мы можем взломать эту функцию, чтобы исправить ее, или есть очень простое обходное решение, которое не требует взлома функции. На самом деле, простое решение, вероятно, предпочтительнее во многих случаях, но сначала я объясню, как взломать функцию, поэтому мы понимаем, почему обходное решение также работает. Прокрутите до конца этого ответа, если вы хотите простое решение:

ОБНОВЛЕНИЕ: Нижеизложенное изменение было реализовано в версии 0.6 на речной карте

Чтобы отредактировать функцию, вы можете использовать

trace(curveseg, edit=T)

Затем найдите строку ближе к концу функции, которая читает

polygon(c(xx[i], xx[i + 1], xx[i + 1], xx[i]), c(yy[i], 
      yy[i + 1], yy[i + 1] + w, yy[i] + w), col = grad[i], 
      border = grad[i])

Мы видим здесь, что авторы пакета решили не передавать параметр lty в polygon (UPDATE: см. этот ответ для объяснения того, почему автор пакета сделал это так). Измените эту строку, добавив lty = 0 (или, если хотите, border = NA), и он работает как предназначен для случая OP. (Но обратите внимание, что это может не сработать, если вы хотите сделать pdf файл - см. здесь)

polygon(c(xx[i], xx[i + 1], xx[i + 1], xx[i]), c(yy[i], 
      yy[i + 1], yy[i + 1] + w, yy[i] + w), col = grad[i], 
      border = grad[i], lty=0)

введите описание изображения здесь

В качестве дополнительной заметки это также объясняет несколько странное поведение в комментариях: "Если вы запускаете его дважды, во второй раз график выглядит нормально, хотя экспортируйте его, а строки возвращаются". Когда lty не указывается при вызове polygon, используемое по умолчанию значение равно lty = par("lty"). Первоначально по умолчанию par("lty") является сплошной линией, но после запуска функции riverplot один раз par("lty") получает значение 0 во время вызова riverplot:::draw.nodes, таким образом, подавление строк, когда riverplot выполняется во второй раз. Но если вы затем попытаетесь экспортировать изображение, открытие нового устройства сбросит значение par("lty") до значения по умолчанию.

Альтернативным способом обновления функции с помощью этого редактирования является использование assignInNamespace для перезаписывания функции пакета с помощью вашей собственной версии. Вот так:

curveseg.new = function (x0, x1, y0, y1, width = 1, nsteps = 50, col = "#ffcc0066", 
          grad = NULL, lty = 1, form = c("sin", "line")) 
{
  w <- width
  if (!is.null(grad)) {
    grad <- colorRampPaletteAlpha(grad)(nsteps)
  }
  else {
    grad <- rep(col, nsteps)
  }
  form <- match.arg(form, c("sin", "line"))
  if (form == "sin") {
    xx <- seq(-pi/2, pi/2, length.out = nsteps)
    yy <- y0 + (y1 - y0) * (sin(xx) + 1)/2
    xx <- seq(x0, x1, length.out = nsteps)
  }
  if (form == "line") {
    xx <- seq(x0, x1, length.out = nsteps)
    yy <- seq(y0, y1, length.out = nsteps)
  }
  for (i in 1:(nsteps - 1)) {
    polygon(c(xx[i], xx[i + 1], xx[i + 1], xx[i]), 
            c(yy[i], yy[i + 1], yy[i + 1] + w, yy[i] + w), 
            col = grad[i], border = grad[i], lty=0)
    lines(c(xx[i], xx[i + 1]), c(yy[i], yy[i + 1]), lty = lty)
    lines(c(xx[i], xx[i + 1]), c(yy[i] + w, yy[i + 1] + w), lty = lty)
  }
}

assignInNamespace('curveseg', curveseg.new, 'riverplot', pos = -1, envir = as.environment(pos))

Теперь для простого решения, которое не требует изменений в функции:

Просто добавьте строку par(lty=0) перед тем, как заговорить!!!

Ответ 2

Вот автор пакета. Я сейчас борюсь за удовлетворительное решение, которое будет включено в следующую версию пакета.

Проблема заключается в том, как R создает PDF файлы по сравнению с растровыми изображениями. В исходной версии пакета, действительно, я передал lty = 0 в polygon() (вы все еще можете увидеть его в комментариях исходного кода). Однако полигоны без границ выглядят хорошо только на графике png. В выходном файле pdf между многоугольниками появляются тонкие белые линии. Посмотрите:

cc <- "#E41A1C90"
plot.new()
rect(0.2, 0.2, 0.4, 0.4, col=cc, border=NA)
rect(0.4, 0.2, 0.6, 0.4, col=cc, border=NA)
dev.copy2pdf(file="riverplot.pdf")

В X или на png результат корректный. Однако, если визуализироваться как PDF, вы увидите тонкую белую линию между перекосами:

введите описание изображения здесь

Когда вы создаете графику riverplot как PDF, такую ​​как выше, это выглядит очень плохо:

введите описание изображения здесь

Поэтому я вынужден добавлять границы, однако забыл про проверку прозрачности. Когда прозрачность не используется, это выглядит нормально - границы пересекаются с полигонами, а также друг с другом, но вы не можете их видеть. Теперь PDF-документ является приемлемым. Однако, если у вас есть прозрачность, это испортит фигуру.

ИЗМЕНИТЬ:

Теперь я загрузил версию 0.6 of riverplot в CRAN. Помимо некоторых новых вещей (теперь вы можете добавить riverplot в любую часть существующего чертежа), по умолчанию он снова использует lty = 0. Однако теперь есть опция "fix.pdf", которую вы можете установить в TRUE, чтобы снова рисовать границы вокруг сегментов.

Нижняя линия и решения на данный момент:

  • Используйте riverplot 0.6`
  • Если вы хотите визуализировать PDF, не используйте прозрачность и используйте fix.pdf = TRUE
  • Если вы хотите использовать прозрачность и PDF, помогите мне решить проблему.