使用bokeh或matplotlib绘制主题

13 投票
1 回答
4028 浏览
提问于 2025-04-18 00:20

我正在尝试从一个模型中绘制主题可视化图。

我想做的事情类似于bokeh的协方差实现,具体可以参考这个链接

我的数据是:

data 1: index,                            topics.   
data 2: index, topics, weights(use it for color). 

其中“主题”就是一组单词。

我该如何将这些数据传给bokeh,以便绘制上面的数据呢?从例子来看,数据处理的方式并不直观。

matplotlib的话,效果看起来像这个链接
显然,单从图中看,无法清楚地知道每个圆圈对应哪个主题。

这是我的matplotlib代码:

x = []
y = []
area = []

for row in joined:
      x.append(row['index']) 
      y.append(row['index'])
      #weight.append(row['score'])
      area.append(np.pi * (15 * row['score'])**2)
scale_values = 1000
plt.scatter(x, y, s=scale_values*np.array(area), alpha=0.5)
plt.show()

有没有什么想法或建议呢?

1 个回答

15

更新: 下面的回答在主要观点上仍然是正确的,但自从Bokeh 0.7版本以来,API稍微有了一些变化,变得更加明确。一般来说,像这样的内容:

rect(...)

应该替换为

p = figure(...)
p.rect(...)

这里是Les Mis示例中相关的代码行,简化到你的情况。我们来看一下:

# A "ColumnDataSource" is like a dict, it maps names to columns of data.
# These names are not special we can call the columns whatever we like.
source = ColumnDataSource(
    data=dict(
        x = [row['name'] for row in joined],
        y = [row['name'] for row in joined],
        color = list_of_colors_one_for_each_row, 
    )
)

# We need a list of the categorical coordinates
names = list(set(row['name'] for row in joined))

# rect takes center coords (x,y) and width and height. We will draw 
# one rectangle for each row.
rect('x', 'y',        # use the 'x' and 'y' fields from the data source
     0.9, 0.9,        # use 0.9 for both width and height of each rectangle 
     color = 'color', # use the 'color' field to set the color
     source = source, # use the data source we created above
     x_range = names, # sequence of categorical coords for x-axis
     y_range = names, # sequence of categorical coords for y-axis
)

几点说明:

  • 对于数字数据,x_rangey_range通常会自动提供。我们在这里需要明确给出它们,因为我们使用的是分类坐标。

  • 你可以随意排列x_rangey_range中的名称,这个顺序就是它们在图表坐标轴上显示的顺序。

  • 我假设你想使用分类坐标。:) 这正是Les Mis示例所做的。如果你想要数字坐标,可以查看这个回答的底部。

另外,Les Mis示例稍微复杂一些(它有一个悬停工具),所以我们手动创建了一个ColumnDataSource。如果你只需要一个简单的图表,可能可以跳过自己创建数据源,直接把数据传给rect

names = list(set(row['name'] for row in joined))

rect(names,    # x (categorical) coordinate for each rectangle
     names,    # y (categorical) coordinate for each rectangle
     0.9, 0.9, # use 0.9 for both width and height of each rectangle
     color = some_colors, # color for each rect
     x_range = names, # sequence of categorical coords for x-axis
     y_range = names, # sequence of categorical coords for y-axis
)

还有一点:这只会在对角线上绘制矩形,也就是x坐标和y坐标相同的地方。根据你的描述,这似乎是你想要的。但为了完整性,也可以绘制x坐标和y坐标不同的矩形。Les Mis示例就是这样做的。

最后,也许你其实并不想要分类坐标轴?如果你只想使用坐标的数字索引,那会更简单:

inds = [row['index'] for row in joined]

rect(inds,    # x-coordinate for each rectangle
     inds,    # y-coordinate for each rectangle
     0.9, 0.9, # use 0.9 for both width and height of each rectangle
     color = some_colors, # color for each rect
)

编辑: 这里有一个完整的可运行示例,使用数字坐标:

from bokeh.plotting import * 

output_file("foo.html")

inds = [2, 5, 6, 8, 9]
colors = ["red", "orange", "blue", "green", "#4488aa"]

rect(inds, inds, 1.0, 1.0, color=colors)

show()

还有一个示例,使用相同的值作为分类坐标:

from bokeh.plotting import * 

output_file("foo.html")

inds = [str(x) for x in [2, 5, 6, 8, 9]]
colors = ["red", "orange", "blue", "green", "#4488aa"]

rect(inds, inds, 1.0, 1.0, color=colors, x_range=inds, y_range=inds)

show()

撰写回答