python - 我在尝试在 Bokeh 中使用 ColumnDataSource 时遇到错误
问题描述
我收到此错误:
TypeError: Object of type Interval is not JSON serializable
这是我的代码。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math
from bokeh.io import output_file, show
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
from bokeh.models import NumeralTickFormatter
def construct_labels(start, end):
labels = []
for index, x in enumerate(start):
y = end[index]
labels.append('({}, {}]'.format(x, y))
return labels
values = {'Length': np.random.uniform(0, 4, 10)}
df = pd.DataFrame(values, columns=['Length'])
bin_step_size = 0.5
# List of bin points.
p_bins = np.arange(0, (df['Length'].max() + bin_step_size), bin_step_size)
# Reduce the tail to create the left side bounds.
p_left_limits = p_bins[:-1].copy()
# Cut the head to create the right side bounds.
p_right_limits = np.delete(p_bins, 0)
# Create the bins.
p_range_bins = pd.IntervalIndex.from_arrays(p_left_limits, p_right_limits)
# Create labels.
p_range_labels = construct_labels(p_left_limits, p_right_limits)
p_ranges_binned = pd.cut(
df['Length'],
p_range_bins,
labels=p_range_labels,
precision=0,
include_lowest=True)
out = p_ranges_binned
counts = out.value_counts(sort=False)
total_element_count = len(df.index)
foo = pd.DataFrame({'bins': counts.index, 'counts': counts})
foo.reset_index(drop=True, inplace=True)
foo['percent'] = foo['counts'].apply(lambda x: x / total_element_count)
foo['percent_full'] = foo['counts'].apply(lambda x: x / total_element_count * 100)
bin_labels = p_range_labels
# Data Container
source = ColumnDataSource(dict(
bins=foo['bins'],
percent=foo['percent'],
count=foo['counts'],
labels=pd.DataFrame({'labels': bin_labels})
))
p = figure(x_range=bin_labels, plot_height=600, plot_width=1200, title="Range Counts",
toolbar_location=None, tools="")
p.vbar(x='labels', top='percent', width=0.9, source=source)
p.yaxis[0].formatter = NumeralTickFormatter(format="0.0%")
p.xaxis.major_label_orientation = math.pi / 2
p.xgrid.grid_line_color = None
p.y_range.start = 0
output_file("bars.html")
show(p)
解决方案
错误来自这里:
source = ColumnDataSource(dict(
bins=foo['bins'],
percent=foo['percent'],
count=foo['counts'],
labels=pd.DataFrame({'labels': bin_labels})
))
bins
你传入的是一个不能interval
被 JSON 序列化的类型。
查看您的代码后,bins
您的绘图中未使用此变量,因此您可以将其更改为:
source = ColumnDataSource(dict(
percent=foo['percent'],
count=foo['counts'],
labels=bin_labels
))
请注意,我还将您的标签更改为bin_labels
,这是一个列表,ColumnDataSource
可以使用列表作为输入。但是您可能需要进一步格式化这些标签,因为现在它们就像
['(0.0, 0.5]',
'(0.5, 1.0]',
'(1.0, 1.5]',
'(1.5, 2.0]',
'(2.0, 2.5]',
'(2.5, 3.0]',
'(3.0, 3.5]',
'(3.5, 4.0]']
您可能希望将它们格式化为更漂亮的东西。
在这个小改动之后,您应该能够看到您的条形图:
推荐阅读
- python - 在 csv 中读取耶稣诞生时的 Python 3 'NoneType'
- c# - Unity Photon 处理匹配数据
- java - 从 xml 添加的片段在 Backstack 中找不到
- spring-boot - 使用 Java 低级 rest 客户端的弹性搜索
- uwp-xaml - 如何使用弹出窗口创建自定义组合框?
- android - kotlin, .Resources$NotFoundException: Resource ID #0x0 , 从 Activity 切换到 View with inflater
- java - 从控制器中删除自动装配并用正常初始化替换它
- directx - 在 d3d11 的情况下,我应该使用什么来代替 d3d9 中的 SetTexture?
- rest - 有没有办法在 Postman 的 API 测试中使用变量名?
- javascript - 有没有办法从两个不同的数组中删除相同的值?