【问题标题】:Scatter plot for non numeric data非数值数据的散点图
【发布时间】:2014-08-04 07:32:38
【问题描述】:

我正在学习将 matplotlib 与 pandas 一起使用,但我遇到了一些麻烦。有一个数据框,其中分别将区域和咖啡店作为其 y 和 x 标签。列值代表各区咖啡店的开业日期

          starbucks    cafe-cool      barista   ........    60 shops
dist1     2008-09-18  2010-05-04     2007-02-21   ...............
dist2     2007-06-12  2011-02-17       
dist3
.
.
100 districts

我想绘制一个散点图,其中 x 轴作为时间序列,y 轴作为咖啡店。由于我无法找出直接的单行方式来绘制此图,因此我将咖啡店提取为一个列表,将日期提取为另一个列表。

shops = list(df.columns.values)
dt = pd.DataFrame(df.ix['dist1'])
dates = dt.set_index('dist1')

首先我尝试了plt.plot(dates, shops)。得到 ZeroDivisionError:整数除法或模除以零 - 错误。我无法弄清楚它的原因。我在一些帖子上看到数据应该是数字的,所以我使用了 ytick 函数。

y = [1, 2, 3, 4, 5, 6,...60] 

仍然plt.plot(dates, y) 抛出相同的 ZeroDivisionError。如果我能通过这可能是我将能够使用刻度函数进行绘图。资源 - http://matplotlib.org/examples/ticks_and_spines/ticklabels_demo_rotation.html

我正在尝试仅绘制第一行/dist1 的图表。为此,我将第一行作为数据帧df1 = df.ix[1] 获取,然后使用以下

for badges, dates in df.iteritems():

    date = dates

    ax.plot_date(date, yval)

    # Record the number and label of the coffee shop
    label_ticks.append(yval)
    label_list.append(badges)
    yval+=1 

。 我在ax.plot_date(date, yval) 行遇到错误,说 x 和 y 应该具有相同的第一维。由于我正在为 dist1 的每个咖啡店一一绘制,所以 x 和 y 的长度不应该始终为 1 吗? PS:date是一个datetime.date对象

【问题讨论】:

  • 日期“2008-09-18”是作为日期时间对象还是字符串传递的?在我看来,您应该遍历每家咖啡店,您能给出一个仅适用于一家咖啡店的最小工作示例吗?
  • 您可以将 x 轴作为日期,将 y 轴作为地区,然后使用第三个变量(用不同颜色表示)来勾勒出 60 家不同的商店。
  • @Greg :日期作为字符串对象传递。您所说的一家咖啡店的工作示例是什么意思?
  • 一旦你弄清楚了你的日期,还有一个很好的方法可以使用答案中的字典将类别映射到数值here

标签: python matplotlib dataframe


【解决方案1】:

要实现这一点,您需要将日期转换为日期时间,请参阅here 一个例子。如前所述,您还需要将咖啡店转换为 一些编号系统然后相应地更改刻度标签。

这是一个尝试

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

def get_datetime(string):
    "Converts string '2008-05-04' to datetime"
    return datetime.strptime(string, "%Y-%m-%d")

# Generate datarame
df = pd.DataFrame(dict(
             starbucks=["2008-09-18", "2007-06-12"],
             cafe_cool=["2010-05-04", "2011-02-17"],
             barista=["2007-02-21"]),
             index=["dist1", "dist2"])

ax = plt.subplot(111)

label_list = []
label_ticks = []
yval = 1 # numbering system

# Iterate through coffee shops
for coffee_shop, dates in df.iteritems():

    # Convert strings into datetime list
    datetimes = [get_datetime(date) for date in dates] 

    # Create list of yvals [yval, yval, ...] to plot against
    yval_list = np.zeros(len(dates))+yval

    ax.plot_date(datetimes, yval_list)

    # Record the number and label of the coffee shop
    label_ticks.append(yval)
    label_list.append(coffee_shop)

    yval+=1 # Change the number so they don't all sit at the same y position

# Now set the yticks appropriately
ax.set_yticks(label_ticks)
ax.set_yticklabels(label_list)

# Set the limits so we can see everything
ax.set_ylim(ax.get_ylim()[0]-1,
            ax.get_ylim()[1]+1)

【讨论】:

  • 这解决了我的问题。我还是不明白为什么我得到了 zerodivisionerror?
  • 我无法用你给的东西复制它。发布一个给出错误并且可能更容易诊断的工作示例。