【问题标题】:Count frequencies of x, y coordinates, display in 2D and plot计算 x、y 坐标的频率,以 2D 显示并绘图
【发布时间】:2016-01-09 20:59:10
【问题描述】:

我试图绘制病毒生物学序列组合的分离年份差异和核苷酸差异发生的频率。我正在尝试找到一种优雅的方式来解决问题。

所以我有一个对齐,我将每个序列相互比较以获得一个整数值,说明它们有多么不同。我还检查了他们被隔离的年份有多么不同。因此,对于一组相隔两年且具有三个差异的序列,您将获得坐标 (2,3)。我想计算(2,3)发生的次数以及所有其他组合并绘制它(并获取绘图数据)。我一直在尝试将频率列表转换为数据框,但无济于事,我想知道是否有更好的方法。

我可以展示一些代码,但我不确定这是最好的方式,所以我想听听其他想法。

一个问题是如何在开始时表示频率。我可以创建所有事件的列表或创建事件字典并增加一个计数器。

样本数据: (年份差异,序列残基差异): (1,2), (2,5), (1,2), (5, 5), (4, 5)

输出显示在图片中,但它不必在表结构中。 CSV 是首选。

【问题讨论】:

标签: python pandas plot


【解决方案1】:

我大量借用this post的表结构。

这里的区别在于构造数组数据。通过用零初始化一个数组,对于每个坐标 (i, j),您将该数组元素递增 1,以表示递增的频率。

zip(*coords) 将所有is 组合在一个元组中,将所有js 组合在另一个元组中。通过找到每个中的最大值,我们知道数组的大小。请注意,这必须比xy 大1 以占0,即从0 到x 是x+1 行。

import matplotlib.pyplot as plt
import numpy as np

from matplotlib.table import Table

def table_plot(data):
    fig, ax = plt.subplots()
    ax.set_axis_off()

    tb = Table(ax, bbox=[0,0,1,1])

    nrows, ncols = data.shape
    width, height = 1.0 / ncols, 1.0 / nrows

    for (i, j), val in np.ndenumerate(data):
        tb.add_cell(i, j, width, height, text=str(val) if val else '', loc='center')

    for i in range(data.shape[0]):
        tb.add_cell(i, -1, width, height, text=str(i), loc='right',
                    edgecolor='none', facecolor='none')
    for i in range(data.shape[1]):
        tb.add_cell(-1, i, width, height/2, text=str(i), loc='center',
                    edgecolor='none', facecolor='none')

    tb.set_fontsize(16)
    ax.add_table(tb)
    return fig

coords = ((1,2), (2,5), (1,2), (5, 5), (4, 5))

# get maximum value for both x and y to allocate the array
x, y = map(max, zip(*coords))
data = np.zeros((x+1, y+1), dtype=int)

for i, j in coords:
    data[i,j] += 1

table_plot(data)
plt.show()

输出:

【讨论】:

  • 感谢您的回答。你这么好!我编辑了这个问题,说我正在寻找 csv 输出,但在行和列中。我不需要线条。很抱歉造成混乱!
  • 感谢您一直以来的帮助。我希望能够计算元组 (1,2) 的频率并得到一个显示行和列频率的 csv 文件。是不是更清楚了?
  • @burkesquires 我想你想要像this 这样的东西。从坐标构造的二维数组应该与我的代码示例中的相同。您还应该记住,问题的内容不应与最初提出的内容发生巨大变化,因为它会使任何当前答案无效。此处的问题和答案应侧重于在绘图中显示 2d 坐标。如果您有无法解决的关于 csv 文件的问题,您应该创建一个新问题。
  • 这行:x, y = map(max, zip(*coords)) 非常有用。星号的用途是什么?
  • @burkesquires 这个unpacks 将列表元素作为单独的参数。所以zip(*[(a, b), (c, d), (e, f)]) 变为zip((a, b), (c, d), (e, f)),结果为[(a, c, e), (b, d, f)]
【解决方案2】:

假设您的(年份,差异)元组位于名为 samples 的列表中,如下例所示

import random
samples = [(random.randint(0,10), random.randint(0,10)) for i in range(100) ]

您可以获得每对的频率,如另一篇stackoverflow帖子How to count the frequency of the elements in a list?中所述

import collections
counter=collections.Counter(samples)

要可视化这个频率表,您可以将其转换为 numpy 矩阵并使用 matplotlib 中的 matshow

import numpy as np
import matplotlib.pyplot as plt

x_max = max([x[0] for x in samples])
y_max = max([x[1] for x in samples])
freq = np.zeros((x_max+1, y_max+1))
for coord, f in counter.iteritems():
    freq[coord[0]][coord[1]] = f
plt.matshow(freq, cmap=plt.cm.gray)
plt.show()

【讨论】:

  • 感谢您的帮助。我已经尝试了一些版本的计数器。当我 tr 上面的解决方案时,我收到错误:AttributeError: 'Counter' object has no attribute 'iteritems'
  • @burkesquires 如果您使用的是 Python 3,则语法已更改为 counter.items()iteritems() 方法只存在于 Python 2 中。
猜你喜欢
  • 2022-09-23
  • 2012-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多