【问题标题】:R: matrix with directional arrowsR:带有方向箭头的矩阵
【发布时间】:2021-04-09 13:27:19
【问题描述】:

我正在尝试使用 R 重现 Sutton 和 Barto (2018) 中描述的算法,但我无法像作者在第 65 页上描述的那样生成带有箭头的矩阵:

我尝试为此目的使用包“字段”,但没有多大成功。

在 Python 中,Shangtong Zhang 和 Kenta Shimada 提出的解决方案 依赖于使用箭头符号: ACTIONS_FIGS=['←', '↑', '→', '↓'] 但这不适用于 R...

编辑:我对初始动作进行了编码,动作以数字方式更新如下:

library(data.table)
action_random = data.table(cell=c(1:25))
action_random$action_up = action_random$action_right = action_random$action_down =
action_random$action_left = rep(1,25)
action_random$proba = rep(1/4,25)
action_random

我还可以修改here 发布的代码,用简单的箭头绘制一个简单的网格:

arrows = matrix(c("\U2190","\U2191","\U2192","\U2193"),nrow=2,ncol=2)
grid_arrows = expand.grid(x=1:ncol(arrows),y=1:nrow(arrows))
grid_arrows$val = arrows[as.matrix(grid_arrows[c('y','x')])]

library(ggplot2)

ggplot(grid_arrows, aes(x=x, y=y, label=val)) + 
  geom_tile(fill='transparent', colour = 'black') + 
  geom_text(size = 14) + 
  scale_y_reverse() +
  theme_classic() + 
  theme(axis.text  = element_blank(),
        panel.grid = element_blank(),
        axis.line  = element_blank(),
        axis.ticks = element_blank(),
        axis.title = element_blank())

但是:
(i) 没有可用于 nice 2 的 unicode 是上面表 $\pi_\ast$ 中报告的 4 向箭头
(ii) ...所以我并没有尝试编写表格“action_random”中的数值和一个带有箭头的漂亮表格之间的双射...

欢迎任何有助于解决问题 (i) 和 (ii) 的提示。

【问题讨论】:

  • 也许您应该提供一些相关代码。
  • @nbro:我添加了一个编辑,其中包含一个简短示例,说明我如何对动作进行数字编码。

标签: r symbols reinforcement-learning


【解决方案1】:

使用包 emojifont 可以让我获得更多 unicode 选项。在您的 ggplot 中添加 family='EmojiOne'。这是一个使用 unicode 的示例

More about the package emojifont here

编辑:破解四向箭头:

不是最漂亮或更优雅的解决方案,但您可以使用包 magick 覆盖 ggplots 以获得方向箭头。制作两个绘图层,一个带有左右箭头 (U+2194),另一个带有上下箭头 (U+2195),然后合并(感谢 @Billy34 让代码更优雅):

library(data.table)
library(magick)

library(ggplot2)
library(emojifont)

#layer 1
arrows1 = matrix(c("\U21B4","\U2195","\U2192","\U2193"),nrow=2,ncol=2)
grid_arrows1 = expand.grid(x=1:ncol(arrows1),y=1:nrow(arrows1))
grid_arrows1$val = arrows1[as.matrix(grid_arrows1[c('y','x')])]

#layer 2
arrows2 = matrix(c("\U21B4","\U2194","\U2192","\U2193"),nrow=2,ncol=2)
grid_arrows2 = expand.grid(x1=1:ncol(arrows2),y1=1:nrow(arrows2))
grid_arrows2$val = arrows2[as.matrix(grid_arrows2[c('y1','x1')])]

ggplot(grid_arrows1, aes(x=x, y=y, label=val),family='EmojiOne') + 
  geom_tile(fill='NA', colour = 'black') + 
  
  geom_text(size = 18) + 
  
  geom_text(grid_arrows2,mapping =  aes(x=x1, y=y1, label=val),size = 18) +
  scale_y_reverse() +
  theme_classic() + 
  theme(
        panel.background = element_rect(fill = "transparent"), # bg of the panel
    plot.background = element_rect(fill = "transparent", color = NA), # bg of the plot
axis.text  = element_blank(),
        panel.grid = element_blank(),
        axis.line  = element_blank(),
        axis.ticks = element_blank(),
        axis.title = element_blank()# get rid of legend panel bg
  ) 
  
#save plot as image
ggsave(filename = 'plot1.png', device = 'png', bg = 'transparent') 


# read images with package magick
 plot1 <- image_read('plot1.png')

image_mosaic(plot1)

更新:

和之前的代码一样粗鲁,但更接近你要找的……

某些 Unicode 仅适用于某些字体,因此第一步是找到适用于您正在寻找的 Unicode 的字体。这是leftwards arrow used in the example below类型的字体支持示例。

当然,列表中的字体都不是标准字体,因为生活并不那么容易。所以下一步是安装字体。我使用了我下载的字体 Symbola here。如果您正在使用项目,请将字体文件复制到您的 R 目录或项目文件夹。

然后使用库showtext。该包允许您在图形中使用系统字体(需要包sysfonts)。如果字体在您的操作系统中是标准字体,我建议您查看包 systemfonts。

在我的示例中,我使用了箭头\U1F800 和\U1F801,然后,就像在我之前的示例中一样,我将它们重叠(PS:您可能不得不在nudge_y 和nudge_x geom_text 让它们正确对齐):

library(data.table)
library(magick)
library(ggplot2)
library(showtext)



#layer 1, upwards arrow
arrows1 = matrix(c("", "\U1F801", "\U1F801", ""),
                 nrow = 2,
                 ncol = 2)
grid_arrows1 = expand.grid(x = 1:ncol(arrows1), y = 1:nrow(arrows1))
grid_arrows1$val = arrows1[as.matrix(grid_arrows1[c('y', 'x')])]

#layer 2 , leftwards arrow
arrows2 = matrix(c("", "\U1F800", "\U1F800", ""),
                 nrow = 2,
                 ncol = 2)
grid_arrows2 = expand.grid(x1 = 1:ncol(arrows2), y1 = 1:nrow(arrows2))
grid_arrows2$val = arrows2[as.matrix(grid_arrows2[c('y1', 'x1')])]

#layer 3 , upwards arrow
arrows3  = matrix(c("\U1F801", "", "", "\U1F801"),
                  nrow = 2,
                  ncol = 2)
grid_arrows3 = expand.grid(x2 = 1:ncol(arrows3), y2 = 1:nrow(arrows3))
grid_arrows3$val = arrows3[as.matrix(grid_arrows3[c('y2', 'x2')])]

#layer 4 , leftwards arrow
arrows4 = matrix(c("\U1F800", "", "", "\U1F800"),
                 nrow = 2,
                 ncol = 2)
grid_arrows4 = expand.grid(x3 = 1:ncol(arrows4), y3 = 1:nrow(arrows4))
grid_arrows4$val = arrows4[as.matrix(grid_arrows4[c('y3', 'x3')])]

#use function font_add from lybrary showtext
 font_add("Symbola", regular = "Symbola_hint.ttf")
# Take a look at the function showtext_auto() as well

 ggplot(grid_arrows1,
        aes(x = x, y = y, label = val),
        family = 'Symbola',
        size = 18) +
   
   geom_tile(fill = 'NA', colour = 'black') +
   geom_text(
     grid_arrows1,
     mapping = aes(x = x, y = y, label = val),
     family = 'Symbola',
     size = 18
   ) +
   
   geom_text(
     grid_arrows2,
     mapping =  aes(x = x1, y = y1, label = val),
     family = 'Symbola',
     size = 18,
     nudge_x = -0.01
   ) +
   geom_text(
     grid_arrows1,
     mapping =  aes(x = x, y = y, label = val),
     family = 'Symbola',
     size = 18,
     angle = 180
   ) +
   geom_text(
     grid_arrows2,
     mapping =  aes(x = x1, y = y1, label = val),
     family = 'Symbola',
     size = 18,
     angle = 180,
     nudge_x = 0.01,
     nudge_y = 0.007
   ) +
   geom_text(
     grid_arrows3,
     mapping =  aes(x = x2, y = y2, label = val),
     family = 'Symbola',
     size = 17,
     nudge_y = 0.03
   ) +
   geom_text(
     grid_arrows4,
     mapping =  aes(x = x3, y = y3, label = val),
     family = 'Symbola',
     size = 17,
     nudge_x = -0.021,
     nudge_y = -0.01
   ) +
   
   scale_y_reverse() +
   theme_classic() +
   theme(
     panel.background = element_rect(fill = "transparent"),
     # bg of the panel
     plot.background = element_rect(fill = "transparent", color = NA),
     # bg of the plot
     axis.text  = element_blank(),
     panel.grid = element_blank(),
     axis.line  = element_blank(),
     axis.ticks = element_blank(),
     axis.title = element_blank()# get rid of legend panel bg
   ) 
 
 #save plot as image
 ggsave(filename = 'plot.png',
        device = 'png',
        bg = 'transparent')
 
 # read images with package magick
 image_read('plot.png')

这是我得到的结果:

我不能说这是见过的最漂亮的代码,它是最骇人听闻的,但它可能会有所帮助! (完成这项工作所花费的时间比我想承认的要多!)

【讨论】:

  • 叠加两个geom_text层不是合并图片更方便吗?
  • 你是绝对正确的,@Billy34。我早些时候遇到了一个错误,没有时间弄清楚为什么它不起作用。但现在我已经编辑了它。谢谢!
  • 感谢您的输入,确实很有趣。但是,通过将水平和垂直 unicode 箭头叠加得到的正交箭头并没有原始箭头那么漂亮。我尝试过使用 tikz,它非常灵活地绘制一组 $2^4-1$ 方向,但无法在 R 中导入 tikz-arrows。
  • 真的,@Bertrand。我尝试了另一种方法。虽然仍然超级“hacky”......
  • 您是否尝试使用包tikzDevice? github.com/daqana/tikzDevice
【解决方案2】:

这里有一种网格+格子的方式来重现矩阵:

library(grid)
library(lattice)

grid.newpage()
pushViewport(viewport(width = 0.8, height = 0.8)) 
grid.rect(width = 1, height = 1)
panel.grid(h = 4, v = 4)

direct = function(xCenter, yCenter, type){
  
  d= 0.05
  
  north = function(xCenter, yCenter){ 
    grid.curve(xCenter, yCenter-d ,xCenter, yCenter+d, 
               ncp = 1, angle = 90, gp=gpar(lwd=1, fill="black"),
               inflect = FALSE, shape = 0,
               arrow = arrow(type="closed", ends = "last", 
                      angle = 30, length = unit(0.2, "cm")))}
  
  west = function(xCenter, yCenter){
    grid.curve(xCenter+d, yCenter ,xCenter-d, yCenter, 
               ncp = 1, angle = 90, gp=gpar(lwd=1, fill="black"),
               inflect = FALSE, shape = 0,
               arrow = arrow(type="closed", ends = "last", 
                             angle = 30, length = unit(0.2, "cm")))}
  east = function(xCenter, yCenter){
    grid.curve(xCenter+d, yCenter ,xCenter-d, yCenter, 
               ncp = 1, angle = 90, gp=gpar(lwd=1, fill="black"),
               inflect = FALSE, shape = 0,
               arrow = arrow(type="closed", ends = "first", 
                             angle = 30, length = unit(0.2, "cm")))}
  
  northeast = function(xCenter, yCenter){
       grid.curve(xCenter-d, yCenter+d ,xCenter+d, yCenter-d, 
                 ncp = 1, angle = 90, gp=gpar(lwd=1, fill="black"),
                 inflect = FALSE, shape = 0,
                 arrow = arrow(type="closed", ends = "both", 
                         angle = 30, length = unit(0.2, "cm")))}
  
  northwest = function(xCenter, yCenter){
       grid.curve(xCenter-d, yCenter-d ,xCenter+d, yCenter+d, 
               ncp = 1, angle = 90, gp=gpar(lwd=1, fill="black"),
               inflect = FALSE, shape = 0,
               arrow = arrow(type="closed", ends = "both", 
                             angle = 30, length = unit(0.2, "cm")))}
  all = function(xCenter, yCenter){
      grid.curve(xCenter+d, yCenter ,xCenter-d, yCenter, 
                 ncp = 1, angle = 90, gp=gpar(lwd=1, fill="black"),
                 inflect = FALSE, shape = 0,
                 arrow = arrow(type="closed", ends = "both", 
                               angle = 30, length = unit(0.2, "cm")))
      grid.curve(xCenter, yCenter-d ,xCenter, yCenter+d, 
             ncp = 1, angle = 90, gp=gpar(lwd=1, fill="black"),
             inflect = FALSE, shape = 0,
             arrow = arrow(type="closed", ends = "both", 
                           angle = 30, length = unit(0.2, "cm")))}
  switch(type,
         'n' = north(xCenter, yCenter),
         'e' = east(xCenter, yCenter),
         'w' = west(xCenter, yCenter),
         'nw'= northwest(xCenter, yCenter),
         'ne' = northeast(xCenter, yCenter),
         'all' = all(xCenter, yCenter)
         )
}

x = seq(0.1, 0.9, by = 0.2)
y = x
centers = expand.grid(x0 = x, y0 = y)

row1 = row2 = row3 = c('ne','n', rep('nw',3))
row4 = c('ne','n','nw','w','w')
row5 = c('e','all','w','all','w')

dir = c(row1,row2,row3,row4,row5)
df = data.frame(centers, dir)

for (k in 1:nrow(df)) direct(df$x0[k], df$y0[k], df$dir[k])
grid.text(bquote(~pi["*"]), y = -0.05)

【讨论】:

  • 非常漂亮的网格。感谢您的帖子,这也让我发现了网格包。
  • 很高兴有帮助。 {grid} 和 {lattice} 包属于基本 R 包,包含在 R 安装程序的每个版本中,因此您无需使用“install.packages()”手动安装它们
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 2017-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多