带线的 Matplotlib 极坐标图

Matplotlib Polar Plot with Lines

尝试使用线而不是条在 Matplotlib 中创建风向图。换句话说,我想要这样的东西(用 Gnuplot 创建),其中线条在整个长度上具有一致的粗细,并从原点沿径向延伸到风速(红色是最新的观察结果,靛蓝是巅峰,老obs越老越黑):

我最接近的是这个(请忽略除了线条之外的任何差异):

我尝试过的所有内容都是以 "fans out" 从原点开始的方式绘制的——无论是条形、线条、箭头等等。这是情节线:

bars = ax.bar(wind_direction, wind_speed, width=.075, linewidth=0.1, edgecolor='black', zorder=3)

解决方案:

感谢@cphlewis 的修复,这里是创建所需绘图的完整代码(就在这条线的正上方)。我在尝试使用 plot 时的错误是在一个命令中绘制所有数据,而不是 'n' 个绘图(单独绘制每一行。)

#! /usr/bin/env python2.6
# -*- coding: utf-8 -*-

import csv
import numpy as np
import matplotlib.pyplot as plt

bar_colors     = ['#333333', '#444444', '#555555', '#666666', '#777777', '#888888', '#999999', 'red']
data_source    = '/Users/username/Dropbox/Public/charts.csv'
num_obs        = 8
final_data     = []
wind_direction = []
wind_speed     = []

# Get the data.
data_file = open(data_source, "r")
csv_data  = csv.reader(data_file, delimiter=',')
[final_data.append(item) for item in csv_data]
data_file.close()

# Grab the column headings for the labels, then delete the row from final_data.
xlabel = final_data[0][24]
ylabel = final_data[0][25]
final_data.pop(0)

# Create lists of data to plot (string -> float).
[wind_direction.append(float(item[24])) for item in final_data]
[wind_speed.append(float(item[25])) for item in final_data]

# Make them the desired length based on num_obs.
wind_direction = wind_direction[len(wind_direction)-num_obs:len(wind_direction)]
wind_speed     = wind_speed[len(wind_speed)-num_obs:len(wind_speed)]

# Polar plots are in radians (not degrees.)
wind_direction = np.radians(wind_direction)


wind = zip(wind_direction, wind_speed, bar_colors) # polar(theta,r)


# Customizations.
plt.figure(figsize=(3, 3))  # Size
ax = plt.subplot(111, polar=True)  # Create subplot
plt.grid(color='#888888')  # Color the grid
ax.set_theta_zero_location('N')  # Set zero to North
ax.set_theta_direction(-1)  # Reverse the rotation
ax.set_xticklabels(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'], color='#666666', fontsize=8)  # Customize the xtick labels
ax.spines['polar'].set_visible(False)  # Show or hide the plot spine
ax.set_axis_bgcolor('#111111')  # Color the background of the plot area.

# Create the plot.
# Note: zorder of the plot must be >2.01 for the plot to be above the grid (the grid defaults to z=2.)
for w in wind:
    ax.plot((0, w[0]), (0, w[1]), color=w[2], linewidth=2, zorder=3)

# Right-size the grid (must be done after the plot), and customize the tick labels.
if max(wind_speed) <= 5:
    ax.yaxis.set_ticks(np.arange(1, 5, 1))
    ax.set_rgrids([1, 2, 3, 4, 5], angle=67, color='#FFFFFF', horizontalalignment='left', verticalalignment='center', fontsize=8)
elif 5 < max(wind_speed) <= 10:
    ax.yaxis.set_ticks(np.arange(2, 10, 2))
    ax.set_rgrids([2, 4, 6, 8, 10], angle=67, color='#FFFFFF', horizontalalignment='left', verticalalignment='center', fontsize=8)
elif 10 < max(wind_speed) <= 20:
    ax.yaxis.set_ticks(np.arange(5, 20, 5))
    ax.set_rgrids([5, 10, 15, 20], angle=67, color='#FFFFFF', horizontalalignment='left', verticalalignment='center', fontsize=8)
elif 20 < max(wind_speed) <= 50:
    ax.yaxis.set_ticks(np.arange(10, 50, 10))
    ax.set_rgrids([10, 20, 30, 40, 50], angle=67, color='#FFFFFF', horizontalalignment='left', verticalalignment='center', fontsize=8)
elif 50 < max(wind_speed):
    plt.text(0.5, 0.5, u'Holy crap!', color='white', horizontalalignment='center', verticalalignment='center', transform=ax.transAxes, bbox=dict(facecolor='red', alpha=0.5))

# Plot circles for current obs and max wind.
fig = plt.gcf()
max_wind_circle = plt.Circle((0, 0), max(wind_speed), transform=ax.transData._b, fill=False, edgecolor='indigo', linewidth=2, alpha=1, zorder=9)
fig.gca().add_artist(max_wind_circle)
last_wind_circle = plt.Circle((0, 0), wind_speed[num_obs-1], transform=ax.transData._b, fill=False, edgecolor='red', linewidth=2, alpha=1, zorder=10)
fig.gca().add_artist(last_wind_circle)

# If latest obs is a speed of zero, plot something that we can see.
if wind_speed[num_obs-1] == 0:
    zero_wind_circle = plt.Circle((0, 0), 0.1, transform=ax.transData._b, fill=False, edgecolor='red', alpha=1)
    fig.gca().add_artist(zero_wind_circle)

# Save it to a file.
plt.savefig('/Users/username/Desktop/wind.png', facecolor='black', edgecolor='none')

预计到达时间:CSV 数据(我不再有生成绘图的确切数据;以下数据是近似值。)

wind_speed.csv

timestamp, wind speed
1970-01-01 00:00:00.000000,4
1970-01-01 01:00:00.000000,4
1970-01-01 02:00:00.000000,10
1970-01-01 03:00:00.000000,7
1970-01-01 04:00:00.000000,10
1970-01-01 05:00:00.000000,8
1970-01-01 06:00:00.000000,7
1970-01-01 07:00:00.000000,4

wind_dir.csv

timestamp,wind direction
1970-01-01 00:00:00.000000,1
1970-01-01 01:00:00.000000,260
1970-01-01 02:00:00.000000,267
1970-01-01 03:00:00.000000,267
1970-01-01 04:00:00.000000,269
1970-01-01 05:00:00.000000,300
1970-01-01 06:00:00.000000,190
1970-01-01 07:00:00.000000,269

您真正的问题是,如何在极坐标图上绘制线条而不是条形图?答案:plot。一个最小且完整的例子:

#! /usr/bin/env python2.6
# -*- coding: utf-8 -*-

import csv
import numpy as np
import matplotlib.pyplot as plt

bar_colors     = ['#333333', '#444444', '#555555', '#666666', '#777777', '#888888', '#999999', '#AA0000']
num_obs        = len(bar_colors)

# Make up some data
wind_direction = (2*3.14)*(np.random.random_sample(num_obs))
wind_speed = 5 * np.random.random_sample(num_obs)
wind = zip(wind_direction, wind_speed, bar_colors) # polar(theta,r)

# Polar plotting
fig = plt.figure(figsize=(3, 3))  # Size
ax = plt.subplot(111, polar=True)  # Create subplot
plt.grid(color='#888888')  # Color the grid
ax.set_theta_zero_location('N')  # Set zero to North

ax.vlines(wind_direction, 0, wind_speed, colors=bar_colors, zorder=3)



fig.show()