Как процентилировать переменные по часам в R?

#python #r

#python #r

Вопрос:

У меня есть задача, которую мне нужно выполнить в R. Я сделал это на python (вероятно, не самым эффективным способом.) Конечная цель: фрейм данных со столбцами start_time, agent, процентиль. Существует ~ 8200 агентов, и бизнес открыт с 7:00 до 23:00, это аннотируется целым числом (7,8, … 23). Мне нужно «повторно процентилировать» эти агенты по часам.

 start_time, agent, percentile
7,          1,     1,
7,          2,     0.99,
...
7,          8200,  0,
...
23,         700,   1,
23,         12,    0.99     
  

Обратите внимание, что (А) каждая комбинация агент: час будет представлена с ее нормализованным счетом. Для справки, эта формула нормализации (x-min)/(max-min) .

Данные, которые у меня есть в настоящее время, выглядят следующим образом. Таблица A (metrics.csv)

 idx,  agent,          percentile
1,    z_agent[1],     1
2,    z_agent[2],     0.05
3,    z_agent[3],     0.5
...
8200, z_agent[8200],  0.99
  

Таблица B (hours.csv)

 agent_idx,  start_hour
1           7
2           7
3           7
4           7
  

код python:

 hours = pd.read_csv('hours.csv')
metrics = pd.read_csv('metrics.csv')

ag_rank = {row['agent']:row['percentile'] for idx,row in metrics.iterrows() if 'agent' in row[0]}
raw_scores = [s for s in ag_rank.values()]
raw_min = min(raw_scores)
raw_max = max(raw_scores)

def normed(x,mn,mx):
    return (x-mn)/(mx-mn)

norm_ag_scores = [normed(x,raw_min,raw_max) for x in raw_scores]

c = 0
for k,v in ag_rank.items():
    n = norm_ag_scores[c]
    ag_rank[k] = n
    c  = 1

import operator
tups = []
starts = sorted([hr for hr in hours['start_hour'].unique()]) 
for hr in starts:
    agents = [f'z_agent[{a}]' for a in hours[hours['start_hour'] == hr]['agent_idx'].unique()]
    a_set = set(agents)
    b_set = set(ag_rank.keys())
    missing = list(a_set.symmetric_difference(b_set))
    scores = [ag_rank[a] for a in agents if a in ag_rank.keys()]
    hi = max(scores)
    low = min(scores)
    sort = {a:normed(s,low,hi) for a,s in zip(agents,scores)}
    sort = sorted(sort.items(),key=operator.itemgetter(1),reverse=True)
    for a,s in sort:
        tups.append((hr,a,s))
    for m in missing:
        tups.append((hr,m,0))
  

И итоговая таблица в том виде, в котором она мне нужна:

 reperc = pd.DataFrame(data=tups,columns=['hour','agent','percentile'])
reperc.head()

>>>
7   z_agent[2853]   1.000000
7   z_agent[6004]   0.855892
7   z_agent[4366]   0.821758
7   z_agent[1742]   0.370188
7   z_agent[21]     0.000000
  

Мои вопросы (A): Как я должен выполнить это влияние в R? И (B, необязательно): какой / есть ли способ добиться этого эффекта в python? Возможно, объединение помогло бы.

Комментарии:

1. Не могли бы вы поделиться примером ввода в допустимом синтаксисе R? dput() это хороший способ копирования / вставки для совместного использования объекта R, включая всю соответствующую информацию о классе, например, dput(metrics[1:5, ]) для первых 5 строк metrics .

2. Кроме того, меня смущает повторное процентилирование. Что x в вашей (x-min)/(max-min) формуле? Это текущий процентиль, и вам нужно пересчитать его по часам?

Ответ №1:

Что-то вроде этого должно работать. С удовольствием протестирую / отлажу, если вы поделитесь воспроизводимыми данными.

 library(dplyr)
metrics %>% 
  left_join(hours, by = c("idx" = "agent_idx")) %>%
  group_by(start_time) %>%
  mutate(
    new_percentile = (percentile - min(percentile)) / (max(percentile) - min(percentile))
  ) %>%
  arrange(start_time, desc(new_percentile))