2017-01-07 1 views
1

У меня есть набор измерений; каждое измерение - одна строка в DataFrame. Я хотел бы добавить столбец к тем измерениям, которые отражают ускорение этого измерения по сравнению со ссылкой. Каждое измерение отличается «набором данных» и «алгоритмом», и для каждой пары алгоритмов набора данных существует эталонное время выполнения.pandas: нормализует значения внутри групп с одним опорным значением для каждой группы (groupby? Split-apply-comb?)

col = ['program', 'dataset', 'algorithm', 'extra', 'runtime'] 
df = pandas.DataFrame(
    [['program-ref', 'dataset-X', 'algorithm-i', 'x', 1.0], 
    ['program-ref', 'dataset-X', 'algorithm-j', 'x', 2.0], 
    ['program-ref', 'dataset-Y', 'algorithm-i', 'x', 3.0], 
    ['program-ref', 'dataset-Y', 'algorithm-j', 'x', 4.0], 
    ['program-B', 'dataset-X', 'algorithm-i', 'x', 5.0], 
    ['program-B', 'dataset-X', 'algorithm-j', 'x', 6.0], 
    ['program-B', 'dataset-Y', 'algorithm-i', 'x', 7.0], 
    ['program-B', 'dataset-Y', 'algorithm-j', 'x', 8.0], 
    ['program-C', 'dataset-X', 'algorithm-i', 'x', 9.0], 
    ['program-D', 'dataset-X', 'algorithm-j', 'x', 10.0], 
    ['program-E', 'dataset-Y', 'algorithm-i', 'x', 11.0], 
    ['program-E', 'dataset-Y', 'algorithm-j', 'x', 12.0], 
    ], columns=col) 

Я хотел бы добавить столбец под названием «ускорение», где «» ускорение для каждого измерения вычисляется как (обратному) во время выполнения для измерения, деленное на время выполнения для опорного измерения (для этого пара данных-набора данных). Например, в DataFrame выше «speedup» для строки 5 (программа B, набор данных X, алгоритм i) должен быть 1/(5.0/1.0).

Это, похоже, экземпляр split-apply-comb (http://pandas.pydata.org/pandas-docs/stable/groupby.html), но функции приложения, показанные там, как правило, представляют собой совокупности всего в группе или функции, входы которых являются только одним конкретным измерением. Здесь мне нужно «применить» контрольное измерение ко всему в своей группе.

Я также добавил столбец «лишний» выше, потому что я хотел бы, чтобы результат был идентичным входу, за исключением нового столбца «speedup», тогда как groupby, похоже, хочет отбросить все столбцы «неудобства».

ответ

1

Мне не нравится настройка ваших данных для достижения ваших целей, так как существует несколько названий программ для каждой комбинации алгоритмов. Также обратите внимание, что подход groupby является посторонним, учитывая ваши данные образца, поскольку существуют уникальные комбинации значений алгоритма набора данных программы. Возможно, ваши настоящие данные имеют разные требования? Если да, пожалуйста, обновите образцы данных, чтобы они соответствовали требованиям. Тем временем попробуйте следующее.

Будет легче объединить опорные значения с остальными данными, чтобы соответствующие значения могли быть более легко связаны друг с другом.

ref_df = df.loc[df['program'] == 'program-ref', ['dataset', 'algorithm', 'runtime']] 
# EDIT: only include the following line if you wish to remove the reference 
# rows from the final output 
# df = df.loc[~(df['program'] == 'program-ref')] 

new_df = pd.merge(df, ref_df, on=['dataset', 'algorithm'], 
           suffixes=['', '_ref']) 

# you don't actually need a groupby since there are unique 
# program-dataset-algorithm combinations. 
new_df['speedup'] = 1/(new_df['runtime']/new_df['runtime_ref']) 

# optional groupby approach 
new_df['speedup'] = new_df.groupby(['program', 'dataset', 'algorithm']).apply(
          lambda x: 1/(x['runtime']/x['runtime_ref'])).values 

>>> new_df.sort_values('program', ascending=False) 
     program dataset algorithm extra runtime runtime_ref speedup 
0 program-ref dataset-X algorithm-i  x  1.0   1.0 1.000000 
3 program-ref dataset-X algorithm-j  x  2.0   2.0 1.000000 
6 program-ref dataset-Y algorithm-i  x  3.0   3.0 1.000000 
9 program-ref dataset-Y algorithm-j  x  4.0   4.0 1.000000 
8  program-E dataset-Y algorithm-i  x  11.0   3.0 0.272727 
11 program-E dataset-Y algorithm-j  x  12.0   4.0 0.333333 
5  program-D dataset-X algorithm-j  x  10.0   2.0 0.200000 
2  program-C dataset-X algorithm-i  x  9.0   1.0 0.111111 
1  program-B dataset-X algorithm-i  x  5.0   1.0 0.200000 
4  program-B dataset-X algorithm-j  x  6.0   2.0 0.333333 
7  program-B dataset-Y algorithm-i  x  7.0   3.0 0.428571 
10 program-B dataset-Y algorithm-j  x  8.0   4.0 0.500000 
+0

Привет @ 3novak, мои данные действительно настроены таким образом. Каждый эксперимент генерирует файл JSON, содержащий его параметры, которые включают в себя программу и набор данных, а также алгоритм и время выполнения. Я бы сказал, что комбинация program/dataset/algorithm уникальна, но вы правы, алгоритм набора данных + имеет несколько возможных программ. Я прочитал файлы JSON с помощью 'data_unfiltered = [json.load (open (jf)) для jf в json_input_files]' then 'df = json_normalize (data_unfiltered)'. Я был бы рад принять другие предложения о том, как вы могли бы организовать это. – jowens

+0

Разве вы не можете разбить его так, как я демонстрирую? Если у вас уже есть данные в формате, который вы опубликовали, мое опубликованное решение должно анализировать его довольно быстро. Я не могу думать о каких-либо других способах обработки данных в оригинальном формате без бесконечных количеств. Возможно, есть способ, хотя! – 3novak

+0

Я понимаю, что ваш подход идет в два этапа, возможно, выход первого шага - «способ, которым я демонстрирую». Шаг 1 добавляет ссылочный столбец с соответствующей ссылочной версией для этой строки. Шаг 2 - это тривиальное применение для создания ускорения, в котором я нуждаюсь. Это похоже на простой подход; Я дам ему вихрь сейчас! – jowens

Смежные вопросы