Получите количество / сумму количества столбцов на плавающем графике hbar - PullRequest
5 голосов
/ 08 мая 2020
• 1000 укажите c сегментов. Другими словами, из приведенного ниже кода и графика я хотел бы создать фрейм данных, выдающий в качестве вывода:
KP 0.0 to KP 0.1  : 1 bar
KP 0.1 to KP 0.5  : 2 bars
KP 0.5 to KP 0.55 : 3 bars
KP 0.55 to KP 0.7 : 2 bars

et c ...

С уважением,

Image plot

import pandas as pd
import matplotlib.pyplot as plt

#Create the pandas dataframe
d = {'KP_from' : [0.12, 0.84, 0.5, 0.7], 'KP_to' : [0.55, 0.05, 0.8, 0.75]}
df = pd.DataFrame(data = d)

#Create relavant variables for the floating hbar plot
start = df[['KP_from','KP_to']].min(axis = 1)
mid = df[['KP_from','KP_to']].mean(axis = 1)
width = abs(df.KP_from - df.KP_to)
yval = range(df.shape[0])

df['Direction'] = ['->' if df.KP_from.iloc[i] < df.KP_to.iloc[i] else '<-' for i in yval]

#Create the mpl figure : floating hbar plot
plt.figure()
plt.xlabel('KP')
plt.barh(y = yval, left = start, width = width)
#Add direction arrows at the center of the floating hbar
for i in yval:
    plt.annotate(df.Direction.iloc[i], xy = (mid[i], yval[i]), va = 'center', ha = 'center')
plt.show()

Ответы [ 3 ]

0 голосов
/ 08 мая 2020

Это скорее проблема пересечения:

# the bar's endpoints in correct order
data = np.sort(df.values, axis=1)

# The limits of interest -- update the limits as you want
limits = [0, 0.1, 0.5, 0.55, 0.7]
limits_data = np.array([[limits[i], limits[i+1]] for i in range(len(limits)-1)])

# intersections
intersect = (np.maximum(data[:,None, 0], limits_data[:, 0]) <
             np.minimum(data[:,1,None], limits_data[:,1]) )


# count intersections by limit points
counts = intersect.sum(0)

Вывод:

array([1, 2, 3, 2])

Чтобы получить ожидаемую распечатку:

for count, (x,y) in zip(counts, limits_data):
    print(f'KP {x} to KP {y}  : {count} bar(s)')

Вывод:

KP 0.0 to KP 0.1  : 1 bar(s)
KP 0.1 to KP 0.5  : 2 bar(s)
KP 0.5 to KP 0.55  : 3 bar(s)
KP 0.55 to KP 0.7  : 2 bar(s)
0 голосов
/ 08 мая 2020

Вот еще один подход. Как уже отмечали другие, это, прежде всего, проблема пересечения, которую можно решить без гистограммы.

def is_present(i_start, i_end, start, end):
    return (
        ((start <= i_start) & (end > i_start)) |
        ((start > i_start) & (end <= i_end))
    )


# Create the pandas dataframe
d = {'KP_from': [0.12, 0.84, 0.5, 0.7], 'KP_to': [0.55, 0.05, 0.8, 0.75]}

intervals = sorted(set(d['KP_from'] + d['KP_to']))
n_bins = [
    sum([is_present(i, j, s, e) for s, e in zip(d['KP_from'], d['KP_to'])])
    for i, j in zip(intervals, intervals[1:])
]

for i, j, c in zip(intervals, intervals[1:], n_bins):
    print(f'KP {i} to KP {j} \t: {c} bars')
0 голосов
/ 08 мая 2020

Ваш вопрос на самом деле сводится к подсчету, сколько полосок в каждом сегменте, я сделал это так:

def create_final(data):

    data = [(x[0],x[1]) if x[0]<x[1] else (x[1],x[0]) for x in data]

    ans = []

    points = [(i[0], 'init') for i in data] + [(i[1], 'end') for i in data]

    points = sorted(points)

    carry = points[0]
    nums = 1
    for i in range(1, len(points)):

        ans.append((carry[0], points[i][0], nums))

        if points[i][1] == 'init':
            nums+=1

        elif points[i][1]=='end':
            nums-=1

        carry = points[i]

    return ans

data = [tuple(x) for x in df[['KP_from', 'KP_to']].values]

create_final(data)
[(0.05, 0.12, 1),
 (0.12, 0.5, 2),
 (0.5, 0.55, 3),
 (0.55, 0.7, 2),
 (0.7, 0.75, 3),
 (0.75, 0.8, 2),
 (0.8, 0.84, 1)]

Я не знаю, какой именно формат вам нужен, но из этого списка кортежей (start, end, number of bars) вы можете построить то, что хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...