使用框可视化数据并在框中添加圆圈/刻度

时间:2014-07-14 04:35:23

标签: matlab matplotlib matlab-figure

我有一个看似简单的任务,如果有人伸出援助之手或指向正确的方向,我将非常感激。

我有一个1和0的向量,我想用以下方式创建这个数据的图:我想要一个两个正方形的垂直块,并且对于向量中的每个元素,我想添加一个计数器(这可能是每个方块中的圆圈,圆点,任何东西。因此,例如,顶部正方形可以计算所有的0和底部正方形可以计算所有的1。

因此,例如,如果我有一个50个零和50个的向量,则在运行此文件的最后,每个块将包含50个圆圈/计数标记。我已经开始创建矩形,如下所示:

axis([0 1 0 1])
rectangle('Position',[0.1,0.3,0.2,0.2])
rectangle('Position',[0.1,0.8,0.2,0.2])

但是当我想根据向量的元素是零还是一个来向每个圆圈添加计数标记时,我会陷入困境。

任何帮助非常感谢!

2 个答案:

答案 0 :(得分:1)

基本问题似乎是如何以美观的方式分配每个框中的标签,圆圈等。 Shai的答案在某一点上是一个很好的答案。如果你接受了这个答案,我建议你使用半透明符号。这样就可以看到重叠的符号。

让我们尝试使用matplotlib

import matplotlib.pyplot as plt
import numpy as np

# input vector with 100 elements:
v = np.random.randint(0,2,100)

# calculate the number of 0's and 1's:
n_zeros = np.sum(v == 0)
n_ones = len(v) - n_zeros

# create the plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim(0,2)
ax.set_ylim(0,4)
ax.add_patch(plt.Rectangle((.5, .5), 1, 1, facecolor='none', edgecolor='k'))
ax.add_patch(plt.Rectangle((.5, 2.5), 1, 1, facecolor='none', edgecolor='k'))

# calculate some random coordinates for zeros and ones
c_zeros = np.array([.6, .6]) + .8 * np.random.random((n_zeros, 2))
c_ones = np.array([.6, 2.6]) + .8 * np.random.random((n_ones, 2))

# plot ones with semi-transparent red
ax.plot(c_ones[:,0], c_ones[:,1], 'o', mfc=(1.,0.,0.,.5), mec='none', markersize=10)
# plot zeros with semi-transparent blue
ax.plot(c_zeros[:,0], c_zeros[:,1], 'o', mfc=(0., 0., 1., .5), mec='none', markersize=10)

我们得到:

enter image description here

此图有两个明显的缺点:

  1. 随机性不提供均匀分布
  2. 标记的大小与缩放级别无关;如果你放大,标记大小保持在10点。
  3. 通过使用圆而不是标记,数字2相对容易修复。 (使用标记可以使代码更简单。)

    但是,另一个问题是有点麻烦。我们很可能希望将圆圈打包到矩形中,以便它们的中心尽可能远离彼此。这被称为包装问题,并没有简单的解决方案。最佳的填料通常相当漂亮,但产生更好的近似在数学上是相当具有挑战性的。

    所以,让我们尝试更简单的事情。我们将始终在一个网格中绘制我们的点,每个行有N行和N或N + 1个项目。

    def find_packing(num_items):
        """Find a reasonable packing of circles into a rectangle
    
        num_items - number of items to pack
    
        Returns: [list of X coordinates], [list of Y coordinates]
                 - lists are normalized so that all coordinates are in the interval [0,1]"""
    
        # get rid of a few special cases:
        if num_items == 0:
            return [],[]
        if num_items == 1:
            return [.5], [.5]
        if num_items == 2:
            return [0., 1.], [.5, .5]
        if num_items == 3:
            return [0., 0., 1.], [0., 1., .5]
    
        # calculate the size of the full square (n >= 2)
        n = int(np.sqrt(num_items))
    
        # determine the required number of rows:
        if num_items > n * (n+1):
            num_rows = n + 1
        else:
            num_rows = n
    
        # determine how may elements we have beyond the full num_rows x n rectangle
        leftovers = num_items - num_rows * n
    
        # let us create a list of row lengths:
        r_lengths = [n] * num_rows
    
        # the leftovers need to be distributed evenly (note the integer division):
        for i in range(leftovers):
            r_lengths[(i * num_rows // leftovers + num_rows / 2) % num_rows] += 1
    
        # let us normalize the coordinates so that the resulting coordinates are always 0,0..1,1
        xcoords = []
        ycoords = []
        row_step = 1. / (num_rows - 1)
        for r in range(num_rows):
            ycoords += [r * row_step] * r_lengths[r]
            xcoords += np.linspace(0, 1, r_lengths[r]).tolist()
    
        return xcoords, ycoords
    

    现在,这很容易集成到绘图代码中:

    # calculate some less random coordinates for zeros and ones
    c_zeros = np.array([.6, .6]) + .8 * np.array(find_packing(n_zeros)).T
    c_ones = np.array([.6, 2.6]) + .8 * np.array(find_packing(n_ones)).T
    

    然后我们对我们的情节做了另一个小改动,以保持正方形:

        ax.set_aspect('equal')
    

    这应该在set_xlim命令之前添加。

    通过这些更改,我们的图表如下所示:

    enter image description here

    (这里我将v中的项目数量更改为200,赔率为0.33 / 0.67,使其看起来更有趣。)

答案 1 :(得分:0)

您可以使用scatter命令绘制圆圈(或方块)。为了避免在同一点上绘制所有标记,您可以考虑在该位置添加一些随机性。

广场的中心

c0 = [0.2, 0.4];
c1 = [0.2, 0.9];

假设您有以下向量

v = [0 0 0 1 1 1 0 1 0 0 1 1 0 0 0 0];

有点随机性

r = 0.025*randn( numel( v ), 2 ); % you may control the "spread" of the markers using the scaling factor here

% do the plot
axis([0 1 0 1]); hold on;
rectangle('Position',[0.1,0.3,0.2,0.2])
rectangle('Position',[0.1,0.8,0.2,0.2])     
s0 = v == 0;
scatter( c0(1)+r(s0,1), c0(2)+r(s0,2), 20, 'ob' ); % blue circles
scatter( c1(1)+r(~s0,1), c1(2)+r(~s0,2), 20, 'ob' ); % blue circles