2017-03-18 3 views
-1

나는 this question 상태와 같은 레이더 플롯을 작성하여 한 걸음 더 나아가려고합니다. 나는 이전 질문이 사용하고있는 동일한 소스 code을 사용합니다. 단, pandas 데이터 프레임과 피벗 테이블을 사용하여 이것을 구현하려고합니다.팬더가있는 matplotlib 레이더 플롯

import numpy as np 
import pandas as pd 
from StringIO import StringIO 

import matplotlib.pyplot as plt 
from matplotlib.projections.polar import PolarAxes 
from matplotlib.projections import register_projection 


def radar_factory(num_vars, frame='circle'): 
    """Create a radar chart with `num_vars` axes.""" 
    # calculate evenly-spaced axis angles 
    theta = 2 * np.pi * np.linspace(0, 1 - 1./num_vars, num_vars) 
    # rotate theta such that the first axis is at the top 
    theta += np.pi/2 

    def draw_poly_frame(self, x0, y0, r): 
     # TODO: use transforms to convert (x, y) to (r, theta) 
     verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta] 
     return plt.Polygon(verts, closed=True, edgecolor='k') 

    def draw_circle_frame(self, x0, y0, r): 
     return plt.Circle((x0, y0), r) 

    frame_dict = {'polygon': draw_poly_frame, 'circle': draw_circle_frame} 
    if frame not in frame_dict: 
     raise ValueError, 'unknown value for `frame`: %s' % frame 

    class RadarAxes(PolarAxes): 
     """Class for creating a radar chart (a.k.a. a spider or star chart) 
     http://en.wikipedia.org/wiki/Radar_chart 
     """ 
     name = 'radar' 
     # use 1 line segment to connect specified points 
     RESOLUTION = 1 
     # define draw_frame method 
     draw_frame = frame_dict[frame] 

     def fill(self, *args, **kwargs): 
      """Override fill so that line is closed by default""" 
      closed = kwargs.pop('closed', True) 
      return super(RadarAxes, self).fill(closed=closed, *args, **kwargs) 

     def plot(self, *args, **kwargs): 
      """Override plot so that line is closed by default""" 
      lines = super(RadarAxes, self).plot(*args, **kwargs) 
      for line in lines: 
       self._close_line(line) 

     def _close_line(self, line): 
      x, y = line.get_data() 
      # FIXME: markers at x[0], y[0] get doubled-up 
      if x[0] != x[-1]: 
       x = np.concatenate((x, [x[0]])) 
       y = np.concatenate((y, [y[0]])) 
       line.set_data(x, y) 

     def set_varlabels(self, labels): 
      self.set_thetagrids(theta * 180/np.pi, labels) 

     def _gen_axes_patch(self): 
      x0, y0 = (0.5, 0.5) 
      r = 0.5 
      return self.draw_frame(x0, y0, r) 

    register_projection(RadarAxes) 
    return theta 

def day_radar_plot(df): 
    fig = plt.figure(figsize=(6,6)) 
    #adjust spacing around the subplots 
    fig.subplots_adjust(wspace=0.25,hspace=0.20,top=0.85,bottom=0.05) 

    ldo,rup = 0.1,0.8   #leftdown and right up normalized 

    ax = fig.add_axes([ldo,ldo,rup,rup],polar=True) 

    N = len(df['Group1'].unique()) 
    theta = radar_factory(N) 

    polar_df = pd.DataFrame(df.groupby([df['Group1'],df['Type'],df['Vote']]).size()) 
    polar_df.columns = ['Count'] 

    radii = polar_df['Count'].get_values() 
    names = polar_df.index.get_values() 

    #get the number of unique colors needed 
    num_colors_needed = len(names) 

    #Create the list of unique colors needed for red and blue shades 
    Rcolors = [] 
    Gcolors = [] 

    for i in range(num_colors_needed): 
     ri=1-(float(i)/float(num_colors_needed)) 
     gi=0. 
     bi=0. 

     Rcolors.append((ri,gi,bi)) 

    for i in range(num_colors_needed): 
     ri=0. 
     gi=1-(float(i)/float(num_colors_needed)) 
     bi=0. 

     Gcolors.append((ri,gi,bi)) 

    from_x = np.linspace(0,0.95,num_colors_needed) 
    to_x = from_x + 0.05 

    i = 0 

    for d,f,R,G in zip(radii,polar_df.index,Rcolors,Gcolors): 
     i = i+1 
     if f[2].lower() == 'no': 
      ax.plot(theta,d,color=R) 
      ax.fill(theta,d,facecolor=R,alpha=0.25) 

      #this is where I think i have the issue 
      ax.axvspan(from_x[i],to_x[i],color=R) 

     elif f[2].lower() == 'yes': 
      ax.plot(theta,d,color=G) 
      ax.fill(theta,d,facecolor=G,alpha=0.25) 

      #this is where I think i have the issue 
      ax.axvspan(from_x[i],to_x[i],color=G) 



    plt.show() 

그래서, 나는 그룹 1 투표 중 하나를 예 또는 아니오의 목록이이 StringIO를 가지고 있고이 번호 type..these 번호에있는 라벨에 있지만 단지 예로서 임의로 가정 해 봅시다 ..

fakefile = StringIO("""\ 
Group1,Type,Vote 
James,7,YES\nRachael,7,YES\nChris,2,YES\nRachael,9,NO 
Chris,2,YES\nChris,7,NO\nRachael,9,NO\nJames,2,NO 
James,7,NO\nJames,9,YES\nRachael,9,NO 
Chris,2,YES\nChris,2,YES\nRachael,7,NO 
Rachael,7,YES\nJames,9,YES\nJames,9,NO 
Rachael,2,NO\nChris,2,YES\nRachael,7,YES 
Rachael,9,NO\nChris,9,NO\nJames,7,NO 
James,2,YES\nChris,2,NO\nRachael,9,YES 
Rachael,9,YES\nRachael,2,NO\nChris,7,YES 
James,7,YES\nChris,9,NO\nRachael,9,NO\n 
Chris,9,YES 
""") 

record = pd.read_csv(fakefile, header=0) 
day_radar_plot(record) 

오류는 Value Error: x and y must have same first dimension입니다. 필자는 필자의 대본에서 지적했듯이 나는 그것에 대한 해결책이 있다고 생각했지만 분명히 잘못된 길로 가고있다. 누구라도 조언이나 조언이 있습니까?

+0

을 투표했다. 또한 오류에 대해보고 할 때 오류가 발생한 행을 나타내는 전체 추적을 포함하십시오. 이러한 값 오류는 보통 최소한의 예가 존재하면 그려지는 배열의 모양을 검사하여 쉽게 찾을 수 있습니다. – ImportanceOfBeingErnest

+0

내가 무엇을 놓치고 있습니까? 나는 지침을 따랐다. – Daniel

+0

가지고있는 코드는 실행 가능하지 않습니다 (누락 된 변수 및 구문 오류가 있음). 최소가 아닙니다 (예 : 색상을 설정하면 오류가 발생하지 않아도됩니다.). 코드를 실행할 수 없으면 오류를 재현 할 수 없습니다. 그러나 오류가 발생한 위치 (어느 행)와 실제로 무엇인지 (역 추적 누락)를 알지도 못합니다. 결국 누군가가 당신을 돕기를 원하거나 원하지 않는다면 당신 자신의 선택입니다. – ImportanceOfBeingErnest

답변

4

나는 당신이하려는 것을 완전히 잃어 버렸기 때문에 주어진 데이터로부터 레이더 차트를 그리는 방법에 대한 해결책을 제공 할 것입니다.

그것은 종종 사람들이 어떻게 질문에 대답합니다 읽어 주시고 [mcve] 이해 예 또는 아니오

enter image description here

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


fakefile = StringIO("""\ 
Group1,Type,Vote 
James,7,YES\nRachael,7,YES\nChris,2,YES\nRachael,9,NO 
Chris,2,YES\nChris,7,NO\nRachael,9,NO\nJames,2,NO 
James,7,NO\nJames,9,YES\nRachael,9,NO 
Chris,2,YES\nChris,2,YES\nRachael,7,NO 
Rachael,7,YES\nJames,9,YES\nJames,9,NO 
Rachael,2,NO\nChris,2,YES\nRachael,7,YES 
Rachael,9,NO\nChris,9,NO\nJames,7,NO 
James,2,YES\nChris,2,NO\nRachael,9,YES 
Rachael,9,YES\nRachael,2,NO\nChris,7,YES 
James,7,YES\nChris,9,NO\nRachael,9,NO\n 
Chris,9,YES""") 

df = pd.read_csv(fakefile, header=0) 
df["cnt"] = np.ones(len(df)) 

pt = pd.pivot_table(df, values='cnt', index=['Group1'], 
        columns=['Vote'], aggfunc=np.sum) 

fig = plt.figure() 
ax = fig.add_subplot(111, projection="polar") 

theta = np.arange(len(pt))/float(len(pt))*2.*np.pi 
l1, = ax.plot(theta, pt["YES"], color="C2", marker="o", label="YES") 
l2, = ax.plot(theta, pt["NO"], color="C3", marker="o", label="NO") 

def _closeline(line): 
    x, y = line.get_data() 
    x = np.concatenate((x, [x[0]])) 
    y = np.concatenate((y, [y[0]])) 
    line.set_data(x, y) 
[_closeline(l) for l in [l1,l2]] 

ax.set_xticks(theta) 
ax.set_xticklabels(pt.index) 
plt.legend() 
plt.title("How often have people votes Yes or No?") 
plt.show() 
+0

고마워요! 나는 그것이 잘못된 길로 가고 있다는 것을 압니다. 나는 내가하고 싶은 것을 설명했다. 나는 판다로 이것을 정확하게 묘사하는 방법을 알고 싶었습니다. 이것은 단지 예일 뿐이며, 당신은 내가 어떤 면모를 정확히 보여주었습니다. 그래서 교훈을 얻었습니다. x와 y 좌표의 첫 번째 차원을 동일하게 유지하려면 피벗 테이블을 만들고 모든 개별 플롯에 대해 numpy로 x 좌표와 y 좌표를 연결해야합니다. 권리? – Daniel

+0

당신이 해야할지 모르겠지만 음모가 당신이 무엇인지 알고 있다면, 여기에 표시된 것처럼 적어도 하나의 가능한 해결책이 있습니다. – ImportanceOfBeingErnest

+0

팬더에는 자동으로이를 수행하는 기능이 없습니다. – Daniel