Рассчитать сгруппированную медиану, если у вас есть числовой интервал c - PullRequest
3 голосов
/ 09 января 2020

Это мой фрейм данных с интервалами (классами) в нем.

     df = pd.DataFrame({'Class': [1,2,3,4,5,6,7,8,9,10,11], 
               'Class Interval': ['16.25-18.75', '18.75-21.25', '21.25-23.75', 
                                  '23.75-26.25', '26.25-28.75', '28.75-31.25',
                                  '31.25-33.75', '33.75-36.25', '36.25-38.75',
                                  '38.75-41.25', '41.25-43.75'],
              '??' : [2,7,7,14,17,24,11,11,3,3,1],
              'Cumulative ??': [2,9,16,30,47,71,82,93,96,99,100],
              '??/n' : [.02,.07,.07,.14,.17,.24,.11,.11,.03,.03,.01],
              'Cumulative ??/n' : [.02, .09,.16,.30,.47,.71,.82,.93,.96,.99,1.00]})
    df

        Class   Class Interval   ??   Cumulative  ??     ??/?    Cumulative  ??/? 
    0   1       16.25-18.75      2          2            0.02   0.02
    1   2       18.75-21.25      7          9            0.07   0.09
    2   3       21.25-23.75      7         16            0.07   0.16
    3   4       23.75-26.25     14         30            0.14   0.30
    4   5       26.25-28.75     17         47            0.17   0.47
    5   6       28.75-31.25     24         71            0.24   0.71
    6   7       31.25-33.75     11         82            0.11   0.82
    7   8       33.75-36.25     11         93            0.11   0.93
    8   9       36.25-38.75     3          96            0.03   0.96
    9   10      38.75-41.25     3          99            0.03   0.99
    10  11      41.25-43.75     1         100            0.01   1.00

Вопрос: Как можно вычислить с помощью python сгруппированную медиану для этого кадра данных?

Вручную это можно сделать, и в результате 29.06.

Я пробовал 'median_grouped':

    # importing median_grouped from the statistics module 
    from statistics import median_grouped

    # printing median_grouped for the set 
    print("Grouped Median is %s" %(median_grouped(df['Class Interval']))) 

Но я получил ошибку:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-26-491000133032> in <module>
      4 
      5 # printing median_grouped for the set
----> 6 print("Grouped Median is %s" %(median_grouped(df['Class Interval'])))

~\Anaconda3\ANACONDA\lib\statistics.py in median_grouped(data, interval)
    463     for obj in (x, interval):
    464         if isinstance(obj, (str, bytes)):
--> 465             raise TypeError('expected number but got %r' % obj)
    466     try:
    467         L = x - interval/2  # The lower limit of the median interval.

TypeError: expected number but got '28.75-31.25'

Чем я пытался создать два столбца (один с нижний предел и один с более высоким пределом), но он дал мне только нижний предел (28,75) / более высокий предел медиана (31,25). Я также пробовал только нижний предел, но, конечно, чем он дает мне 28,75.

У меня нет значений в интервалах, так что я не могу переделать список значений, чтобы вырезать с помощью pd.cut и попробовать это так (я не хочу угадывать), но я также попытался вручную сделать интервал класса в бинах (например, 16.25-18.25 чем (16.25,18.25], но затем я получил сообщение об ошибке: TypeError: неупорядоченные типы: Interval ()

Есть ли возможность сделать столбец с интервалом цифрой c вместо строки, чтобы можно было автоматически вычислять сгруппированную медиану с помощью Python?

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Сначала я бы преобразовал ваши интервалы в два отдельных столбца для lower bound (фунт) и upper bound (ub)

df = (df.join(df['Class Interval'].str.split('-', expand=True)
                                  .apply(pd.to_numeric)
                                  .rename(columns={0: 'lb', 1: 'ub'}))
        .drop('Class Interval', 1))

Затем, похоже, вы можете просто написать формулу сразу

enter image description here

m = len(df)//2
gmedian = df.loc[m, 'lb'] + ((df['??'].sum()/2 - df.loc[m - 1, 'Cumulative ??'])/(df.loc[m, '??']))*(df['ub'] - df['lb']).loc[m]

Или, более дидактически c,

L = df.loc[m, 'lb']
N = df['??'].sum()
F = df.loc[m - 1, 'Cumulative ??']
f = df.loc[m, '??']
C = (df['ub'] - df['lb']).loc[m]

gmedian = L + ((N/2 - F)/(f))*C

Выходы

29.0625
1 голос
/ 09 января 2020

Вы можете воссоздать список искусственных точек данных, содержащих одинаковую статистическую информацию (среднее значение каждого интервала * fi интервала), и запустить в них функцию mean_grouped:

# Obtaining lower, upper and middle interval value
df['lower'] = df['Class Interval'].str.split('-', expand=True)[0].astype(float)
df['upper'] = df['Class Interval'].str.split('-', expand=True)[1].astype(float)
df['middle'] = (df['lower'] + df['upper'] ) / 2

# Generating an artificial list of values with the same statistical info
artificial_data_list = []
for index, row in df.iterrows():
  artificial_data_list.append([row['middle']]*row['??'])
flat_list = [item for sublist in artificial_data_list for item in sublist]

# Calcuating the right median with the statistics.mean_grouped function
median_grouped(flat_list,interval=2.5)   # Attention to the interval size!
# => 29.0625
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...