【问题标题】:visualize a two-dimensional point set using Python使用 Python 可视化二维点集
【发布时间】:2022-11-05 01:02:42
【问题描述】:

我是 Python 新手,想执行一个相当简单的任务。我有一个二维点集,它以二进制数据(即(x, y)-坐标)的形式存储在我想要可视化的文件中。输出应如下图所示。

然而,我不知何故被关于这个主题的谷歌搜索结果的数量所淹没。其中许多似乎用于三维点云可视化和/或大量数据点。因此,如果有人能为我的问题指出一个合适的解决方案,我将非常感激。

编辑:点集包含在格式如下的文件中:

0.000000000000000   0.000000000000000
1.000000000000000   1.000000000000000
1
0.020375738732779   0.026169010160356
0.050815740313746   0.023209931647163
0.072530406907906   0.023975230642589

第一个数据向量是单个“1”下方的行中的那个;即(0.020375738732779, 0.026169010160356)。如何在 python 中将其读入向量?我可以使用f = open("pointset file") 打开文件

【问题讨论】:

  • - 你想让输出看起来或多或少确切地就像在示例图像中一样? - 您是否希望将这些点绘制成一个按比例绘制的图像/图表,以便在绘制这些点时保持它们占据的空间的纵横比?或者您不介意纵横比是否偏斜以适合给定比例的视口/窗口..?
  • 文件中的数据是如何格式化的?您在问题中说它是二进制格式的,但是您的示例似乎以纯文本形式显示数据。它是哪一个?
  • 这个问题可以分解为 3 个子问题:1)如何在文件中查找特定行 2)如何在 python 中加载文本文件数据和 3)如何显示散点图。如果您查询它们,所有这些答案都存在于 SO 中。对于 1,使用 open(f, "r").readlines(),并搜索与等于 "1\n" 的行对应的行号。对于 2),使用 numpy.loadtxt 和从 1) 推导出的 skiprows 参数。对于 3) ,我建议matplotlib.scatter

标签: python visual-studio visualization


【解决方案1】:

安装并导入 matplotlib 和 pyplot:

import matplotlib.pyplot as plt

假设这是您的数据:

x = [1, 2, 5, 1, 5, 7, 8, 3, 2, 6]
y = [6, 7, 1, 2, 6, 2, 1, 6, 3, 1]

如果需要,可以使用推导将坐标拆分为单独的列表:

x = [p[0] for p in points]
y = [p[1] for p in points]

绘图很简单:

plt.scatter(x=x, y=y)

结果:

许多定制是可能的。

编辑:以下问题编辑

为了读取文件:

x = []
y = []
with open('pointset_file.txt', 'r') as f:
    for line in f:
        coords = line.split(' ')
        x.append(float(coords[0]))
        y.append(float(coords[1]))
  

【讨论】:

  • 谢谢您的回答。矢量包含在我在问题中编辑的格式的文件中?你能告诉我如何将向量读入python中的向量吗?
  • 使用 open("data.txt") 作为 fid:lines = fid.read().split(" ") data = [[float(d) for d in line.split(" ") if d] for line in lines[3:]] plt.scatter(data[0], data[1])
  • 也许是因为我在 Visual Studio 创建的 Python 应用程序中运行代码,但是在 plt.scatter(x=x, y=y) 行立即关闭后打开的带有绘图的窗口...
  • 哦,在您上面的代码中,x.append(float(coords[0])) 还将float(coords[0]) 添加到y;不仅是x。我不熟悉python,但我猜x 是对与y 所指相同对象的引用。如果我将x = y = [] 替换为x = []y = [],那么一切都会按预期进行。
  • 这种差异与列表指针有关。 x=y=[] 只在内存中创建一个两个变量都引用的列表。附加到x 然后从y 读取将显示相同的内存变化。许多人将 Jupyter 与 matplotlib 一起使用,因此他们不会立即关闭窗口,但您应该在程序末尾添加一行 input() 以便它在窗口打开时暂停。如果有帮助,请接受 Omri 的回答。
【解决方案2】:

您可以按如下方式读取数据,并使用散点图进行绘图。此方法正在考虑少量数据而不是 csv,只是您提供的格式。

import matplotlib.pyplot as plt
with open("pointset file") as fid:
   lines = fid.read().split("
")

# lines[:2] looks like the bounds for each axis, if yes use it in plot 
data = [[float(d) for d in line.split(" ") if d] for line in lines[3:]]   
plt.scatter(data[0], data[1])
plt.show()

【讨论】:

    【解决方案3】:

    假设您想要一个看起来与您提供的示例图像非常相似的图,并且您希望该图以相等的比例显示两个轴的数据,可以使用像 pygame 这样的通用多媒体库来实现这一点:

    #!/usr/bin/env python3
    
    import sys
    import pygame
    
    # windows will never be larger than this in their largest dimension
    MAX_WINDOW_SIZE = 400
    BG_COLOUR = (255, 255, 255,)
    FG_COLOUR = (0, 0, 0,)
    DATA_POINT_SIZE = 2
    
    pygame.init()
    
    if len(sys.argv) < 2:
        print('Error: need filename to read data from')
        pygame.quit()
        sys.exit(1)
    else:
        data_points = []
        # read in data points from file first
        with open(sys.argv[1], 'r') as file:
            [next(file) for _ in range(3)]  # discard first 3 lines of file
            # now the rest of the file contains actual data to process
            data_points.extend(tuple(float(x) for x in line.split()) for line in file)
        # file read complete. now let's find the min and max bounds of the data
        top_left = [float('+Inf'), float('+Inf')]
        bottom_right = [float('-Inf'), float('-Inf')]
        for datum in data_points:
            if datum[0] < top_left[0]:
                top_left[0] = datum[0]
            if datum[1] < top_left[1]:
                top_left[1] = datum[1]
            if datum[0] > bottom_right[0]:
                bottom_right[0] = datum[0]
            if datum[1] > bottom_right[1]:
                bottom_right[1] = datum[1]
        # calculate space dimensions
        space_dimensions = (bottom_right[0] - top_left[0], bottom_right[1] - top_left[1])
        # take the biggest of the X or Y dimensions of the point space and scale it
        # up to our maximum window size
        biggest = max(space_dimensions)
        scale_factor = MAX_WINDOW_SIZE / biggest  # all points will be scaled up by this factor
        # screen dimensions
        screen_dimensions = tuple(sd * scale_factor for sd in space_dimensions)
        # basic init and draw all points to screen
        display = pygame.display.set_mode(screen_dimensions)
        display.fill(BG_COLOUR)
        for point in data_points:
            # translate and scale each point
            x = point[0] * scale_factor - top_left[0] * scale_factor
            y = point[1] * scale_factor - top_left[1] * scale_factor
            pygame.draw.circle(display, FG_COLOUR, (x, y), DATA_POINT_SIZE)
        pygame.display.update()
    
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit(0)
            pygame.time.wait(50)
    

    执行此脚本并将保存数据的文件的名称作为第一个参数传递。它将生成一个显示数据点的窗口。

    我生成了一堆均匀分布的随机 x,y 点来测试它,其中:

    from random import random
    
    for _ in range(1000):
        print(random(), random())
    

    这会产生一个如下所示的窗口:

    如果您的数据点所在的空间不是正方形大小,则窗口形状将改变以反映这一点。窗口的最大尺寸,无论是宽度还是高度,都将始终保持在指定的大小(我在演示中使用 400px 作为默认值)。

    诚然,这不是最优雅或最简洁的解决方案,并且有点重新发明轮子,但是它使您可以最大程度地控制如何显示数据点,并且还可以处理文件数据的读入和显示它。

    【讨论】:

      【解决方案4】:

      要阅读您的文件:

      import pandas as pd
      import numpy as np
      
      df = pd.read_csv('your_file',
                       sep='s+', 
                       header=None,
                       skiprows=3,
                       names=['x','y'])
      

      现在我已经创建了一个随机数据集

      import random
      
      df = pd.DataFrame({'x':[random.uniform(0, 1) for n in range(100)],
                         'y':[random.uniform(0, 1) for n in range(100)]})
      

      对于任何类型的人物,我都更喜欢 Plotly

      import plotly.express as px
      
      fig = px.scatter(df,
                       x='x',
                       y='y')
      fig.show()
      

      从这里您可以轻松地更新标签、颜色等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-15
        • 2021-10-15
        • 1970-01-01
        • 2018-11-16
        • 2021-05-18
        • 2020-05-05
        • 2020-12-17
        • 1970-01-01
        相关资源
        最近更新 更多