【问题标题】:Python: how to create scatterplots of fixed ranges, across several intervals?Python:如何跨多个间隔创建固定范围的散点图?
【发布时间】:2017-09-29 10:26:59
【问题描述】:

我有以下熊猫数据框:

import pandas as pd
df = pd.read_table(...)
df

>>> df
>>>    interval  location type  y_axis
0        01      1230    X      50
1        01      1609    X      55
2        01      1903    Y      54
3        01      2574    A      58
4        01      3151    A      57
5        01      3198    B      46
6        01      3312    X      50
...                 .....
         02      42      X      31
         02      214     A      23
         02      598     X      28
....

有几个间隔,例如0102 等。在每个区间内,数据点位于 1 到 10,000 的范围内。在df 中,第一个数据点在 40,下一个在 136,依此类推。

间隔02 的范围也从 1 到 15,000。

我想创建一个散点图,以便为每个间隔按比例绘制 1 到 15000 的范围。然后第一个点将绘制在 1230 处,下一个点绘制在 1609 处,等等。我还想要一条垂直线来显示间隔的位置。散点图的 x 轴间距应为 1 到 10,000。每个区间都是一个“区域”,包含从 1 到 10,000 的 x 轴。所以x轴上的坐标是interval1:1到15000,interval2:1到15000,interval 3:1到15000等。(几乎就像几个单独的散点图串联在一起。)

如何做到这一点?如果没有这种复杂的区间,如果希望从此 DataFrame 创建散点图,可以使用:

df.plot(kind='scatter', x = "location", y = "y_axis")

这里是前 50 行:

d = {"interval" : ["01",                                                                                                                                                                                                              
 "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", "01",                                                                                                                                                                                                          
 "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", "01",                                                                                                                                                                                                          
 "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", "01",                                                                                                                                                                                                          
 "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", "01",                                                                                                                                                                                                          
 "01", "01", "01", "01", "01"], "location" : [1230, 1609,                                                                                                                                                                                                      
 1903, 2574, 3151, 3198, 3312, 3659, 3709,                                                                                                                                                                                                      
 3725, 4172, 4542, 4860, 4900, 5068, 5220,                                                                                                                                                                                                      
 5260, 5339, 5442, 5529, 5773, 6128, 6165,                                                                                                                                                                                                      
 6177, 6269, 6275, 6460, 7167, 7361, 7361,                                                                                                                                                                                                      
 8051, 8222, 8305, 8992, 9104, 9439, 9844,                                                                                                                                                                                                      
 10045, 10764, 10787, 11104, 11478, 11508,                                                                                                                                                                                                          
 11684, 12490, 12590, 12794, 12803, 13823,                                                                                                                                                                                                          
 13982], "type" : ["X", "X", "Y", "A", "A",                                                                                                                                                                                                              
     "B", "X", "X", "X", "B", "B", "A", "A", "A", "B", "B", "X",                                                                                                                                                                                                            
     "B", "Y", "X", "X", "Y", "Y", "C", "A", "X", "X", "Z", "Z",                                                                                                                                                                                                            
     "B", "X", "X", "A", "A", "Y", "X", "A", "X", "X", "Z", "Z",                                                                                                                                                                                                            
     "C", "X", "Y", "Y", "Z", "Z", "Z", "Z", "Z"],  "y_axis" : [50, 55, 
    54, 58, 57, 46, 50, 55, 46, 42, 56, 55, 55, 45, 52, 51, 45, 48, 50,
     49, 53, 55, 45, 40, 49, 37, 52, 58, 52, 4, 58, 52, 49, 58, 50, 55, 
    56, 53, 58, 43, 55, 55, 44, 52, 59, 49, 53, 39, 60, 52]}

【问题讨论】:

  • 理解您的问题有点困难,因为存在一些不一致之处。 (1) dt 是指 df 吗? (2) 你说第一个数据点是 40,第二个是 136。但是这些值在你的示例数据中在哪里? (3) 您的前 50 行仅包含一个 interval 值。您能否提供捕获多个间隔的示例数据? (4) 如果您可以提供草图或链接到您想要的情节示例,将会很有帮助 - 根据您的描述,这并不容易可视化。
  • 我什至会认为这个问题完全不清楚,因此无法回答。
  • @andrew_reece 抱歉。我更正了一些值。 (1) 现在都是df (2) 看示例数据 (3) 事情很快就会变大。想象一下locationtypey_axis 的相同数据,除了interval 的值全部为02。我将提供一个示例图
  • @andrew_reece 这是我的意思的一个例子。这是一个散点图,已划分为几个区域。 imgur.com/a/l6BvG 每个区域都有相同的数据点间隔,从 1 到 15000。因此设置 x 轴很棘手,因为这些点将混合在一起。我现在说得通吗?
  • @ImportanceOfBeingErnest 给定编辑/cmets,现在清楚了吗?

标签: python pandas matplotlib dataframe scatter-plot


【解决方案1】:

您似乎想为每个类别“间隔”绘制不同的散点图。
这可以通过按相应列对数据框进行分组来完成。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

cat = ["01"] *5 + ["02"]*4
x = np.append(np.arange(1,6), np.arange(2.5,4.1,0.5))
y = np.random.randint(12,24, size=len(cat))
df = pd.DataFrame({"cat":cat, "x":x, "y":y})

fig, ax = plt.subplots()
colors={"01":"crimson", "02":"darkblue"}
for cat, grouped in df.groupby("cat"):
    grouped.plot(kind="scatter", x="x", y="y", ax=ax, label=cat, color=colors[cat])

plt.show()

【讨论】:

  • 现在我看到了图像,这不是我的意思。请参阅@andrew_reece 的回答。红/蓝点应该分开。
  • 你总能得到你想要的。如果这个问题像这里的这个问题一样不清楚,你可能会得到任何类型的答案。您可能会决定下次提供清晰的问题描述,然后获得更适合您需求的答案。
  • 这很公平。我感谢你指出它是多么不清楚----我已经编辑过了。我也感谢您的帮助。没有难过的感觉或任何东西......
【解决方案2】:

似乎这里的主要挑战是您希望 x 轴既是分类的(间隔 0102 等)又是度量的(值 1-15000)。正如您甚至在帖子中指出的那样,您实际上是在谈论使用共享 y 轴绘制多个散点图。我建议你这样做,使用subplotsgroupby。您可以使用subplots_adjust() 调整绘图之间的空间,就像我在这个答案中所做的那样。

首先,使用来自 OP 的d 生成一些示例数据。我们还将随机选择一半的观察结果并将其更改为interval=02,以演示所需的面板:

import pandas as pd
import numpy as np

df = pd.DataFrame(d)

# shuffle rows 
# (taken from this answer: http://stackoverflow.com/a/15772330/2799941)
df = df.reindex(np.random.permutation(df.index))

# randomly select half of the rows for changing to interval 02
interval02 = df.sample(int(df.shape[0]/2.)).index
df.loc[interval02, 'interval'] = "02"

现在使用pyplot 指定并排的子图,并删除图之间的任何填充。

from matplotlib import pyplot as plt

# n_plots = number of different interval values
n_plots = len(df.interval.unique())

fig, axes = plt.subplots(1, n_plots, figsize=(10,5), sharey=True)

# remove space between plots
fig.subplots_adjust(hspace=0, wspace=0)

最后,groupby interval 和情节:

for i, (name, group) in enumerate(df.groupby('interval')):
    group.plot(kind="scatter", x='location', y='y_axis', 
               ax=axes[i], title="Interval {}".format(name))

【讨论】:

    【解决方案3】:

    使用 Altair,您可以轻松地将两个区间分隔为不同的列/颜色。

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    cat = ["01"] *5 + ["02"]*4
    x = np.append(np.arange(1,6), np.arange(2.5,4.1,0.5))
    y = np.random.randint(12,24, size=len(cat))
    df = pd.DataFrame({"cat":cat, "x":x, "y":y})
    

    按列

    from altair import *
    Chart(df).mark_point().encode(x='x', y='y', column='cat').configure_cell(width=200, height=150)
    

    按颜色

    from altair import *
    Chart(df).mark_point().encode(x='x', y='y', color='cat').configure_cell(width=200, height=150)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多