【问题标题】:From scatter plot to 2D array从散点图到二维数组
【发布时间】:2017-01-21 08:34:12
【问题描述】:

我脑子里一片空白。

我想做我认为很简单的事情。

假设我有一些测试数据:

import pandas as pd
import numpy as np
k=10
df = pd.DataFrame(np.array([range(k), 
                           [x + 1 for x in range(k)],
                           [x + 4 for x in range(k)], 
                           [x + 9 for x in range(k)]]).T,columns=list('abcd'))

其中行对应时间,列对应角度,如下所示:

   a   b   c   d
0  0   1   4   9
1  1   2   5  10
2  2   3   6  11
3  3   4   7  12
4  4   5   8  13
5  5   6   9  14
6  6   7  10  15
7  7   8  11  16
8  8   9  12  17
9  9  10  13  18

然后出于某些原因,我将其转换为有序字典:

def highDimDF2Array(df):
    from collections import OrderedDict # Need to preserve order

    vels = [1.42,1.11,0.81,0.50]

    # Get dataframe shapes
    cols = df.columns

    trajectories = OrderedDict()
    for i,j in enumerate(cols):
        x = df[j].values
        x = x[~np.isnan(x)]

        maxTimeSteps = len(x)
        tmpTraj = np.empty((maxTimeSteps,3))
        # This should be fast
        tmpTraj[:,0] = range(maxTimeSteps) 
        # Remove construction nans
        tmpTraj[:,1] = x
        tmpTraj[:,2].fill(vels[i])

        trajectories[j] = tmpTraj

    return trajectories

然后我把它全部画出来

import matplotlib.pyplot as plt
m = highDimDF2Array(df)
M = np.vstack(m.values())
plt.scatter(M[:,0],M[:,1],15,M[:,2])
plt.title('Angle $[^\circ]$ vs. Time $[s]$')
plt.colorbar()
plt.show()

现在我要做的就是将所有这些放入具有属性的 2D numpy 数组中:

  • 时间映射到 x 轴(或 y 无关紧要)
  • 角度映射到 y 轴
  • 矩阵中的条目对应于散点图中彩色点的值
  • 所有其他条目都被视为NaNs(即那些未由散点图中的点定义的条目)

在 3D 中,颜色将对应于高度。

我正在考虑使用这样的东西:3d Numpy array to 2d,但不太确定如何使用。

【问题讨论】:

    标签: python arrays numpy matplotlib


    【解决方案1】:

    您可以将 M[:,1] 和 M[:,2] 中的值转换为整数,并将它们用作二维 numpy 数组的索引。这是一个使用您定义的 M 值的示例。

    out = np.empty((20,10))
    out[:] = np.NAN
    N = M[:,[0,1]].astype(int)
    out[N[:,1], N[:,0]] = M[:,2]
    plt.scatter(M[:,0],M[:,1],15,M[:,2])
    plt.scatter(M[:,0],M[:,1],15,M[:,2])
    plt.title('Angle $[^\circ]$ vs. Time $[s]$')
    plt.colorbar()
    plt.imshow(out, interpolation='none', origin = 'lower')
    

    在这里您可以直接将 M 转换为整数,但您可能必须想出一个函数来根据您创建的数组的分辨率将 M 的列映射为整数。

    【讨论】:

    • 不应该 M = M.astype(int) 是 M = M[:,[0,1]].astype(int) 否则你把它全部变成整数。
    • out[:] = np.NAN N = M[:,[0,1]].astype(int) out[N[:,0], N[:,1]] = M[:,2]
    【解决方案2】:

    我不使用 pandas,所以我无法真正遵循您的功能。但从你的数组 M 的描述和你想要的,我认为功能 np.histogram2d 是你想要的。它以等距的步长对您的独立值的范围进行分类,并对所有出现的次数求和。您可以使用第 3 列进行加权以获得适当的高度。您必须选择垃圾箱的数量:

    z, x, y   = np.histogram2d(M[:,0], M[:,1], weights=M[:,2], bins=50)
    num, x, y = np.histogram2d(M[:,0], M[:,1], bins=50)
    
    z /= num # proper averaging, it also gives you NaN where num==0
    
    plt.pcolor(x, y, z) #visualization
    

    plt.hist2d 也可能很有趣

    编辑: histogram2d 产生问题中要求的二维数组。然而,可视化应该使用 imshow 完成,因为 pcolor 不会跳过 NaN 值(有什么方法可以教它吗?)

    这种方法的优点是 x,y 值可以是浮点数和任意顺序。此外,通过定义 bin 的数量,可以选择结果图像的分辨率。 然而,要准确获得所要求的结果,应该这样做:

    binx = np.arange(M[:,0].min()-0.5, M[:,0].max()+1.5) # edges of the bins. 0.5 is the half width
    biny = np.arange(M[:,1].min()-0.5, M[:,1].max()+1.5)
    
    z,   x, y   = np.histogram2d(M[:,0], M[:,1], weights=M[:,2], bins=(binx,biny))
    num, x, y   = np.histogram2d(M[:,0], M[:,1], bins=(binx,biny))
    
    z /= num
    
    
    plt.imshow(z.T, interpolation='none', origin = 'lower')
    

    pcolor 的输出不会遗漏 nans,但也会考虑 x 和 y 值:

    plt.pcolormesh(x, y, z.T, vmin=0, vmax=2)
    

    【讨论】:

    • 感谢您的回答,关于熊猫,我已更新问题以包含测试数据结构的详细信息。
    • 熊猫部分对你的问题真的很重要吗?
    • 并非如此,更重要的是可以快速轻松地建立 MWE。我使用 pandas 是因为它让我的生活变得轻松,但 numpy 之类的也很好。
    • 我不会说谎,但我没有工作我不敢说;它只会创建一个大像素。
    • 我鼓励您再试一次,因为这是执行您要求的更通用的方法。不过,我知道上面的其他答案适用于您的特殊情况。
    猜你喜欢
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 2021-12-26
    • 2015-01-17
    • 1970-01-01
    • 2020-09-21
    相关资源
    最近更新 更多