2016-06-01 3 views
1

У меня есть панд DataFrame df как этотРазделить ряды питона панд DataFrame

mat time 
0 101 20 
1 102 7 
2 103 15 

Мне нужно разделить строки так, столбец времени не имеет значения выше, чем t=10 иметь что-то вроде этого

mat time 
0 101 10 
2 101 10 
3 102 7 
4 103 10 
5 103 5 

индекс не имеет значения

Если бы я использовать GroupBy («мат») [ «время»]. (сумма) на этом ФР я бы оригинальный df, но мне нужно как бы инвертировать функцию groupby func.

Есть ли способ получить ungrouped DataFrame с условием time <= t?

Я пытаюсь использовать петлю здесь, но это своего рода «unPythonic», любые идеи?

ответ

1

Используйте apply функцию, что петли, пока все не меньше 10.

def split_max_time(df): 
    new_df = df.copy() 
    while new_df.iloc[-1, -1] > 10: 
     temp = new_df.iloc[-1, -1] 
     new_df.iloc[-1, -1] = 10 
     new_df = pd.concat([new_df, new_df]) 
     new_df.iloc[-1, -1] = temp - 10 
    return new_df 


print df.groupby('mat', group_keys=False).apply(split_max_time) 

    mat time 
0 101 10 
0 101 10 
1 102  7 
2 103 10 
2 103  5 
1

Вы можете .groupby('mat') и .apply() сочетание integer разделения и modulo операции с использованием cutoff (10) для разложения каждого time значения в Нужные компоненты:

cutoff = 10 
def decompose(time): 
    components = [cutoff for _ in range(int(time/cutoff))] + [time.iloc[0] % cutoff] 
    return pd.Series([c for c in components if c > 0]) 

df.groupby('mat').time.apply(decompose).reset_index(-1, drop=True) 

, чтобы получить:

mat 
101 10 
101 10 
102  7 
103 10 
103  5 

В случае, если вы заботитесь о производительности:

%timeit df.groupby('mat', group_keys=False).apply(split_max_time) 
100 loops, best of 3: 4.21 ms per loop 

%timeit df.groupby('mat').time.apply(decompose).reset_index(-1, drop=True) 
1000 loops, best of 3: 1.83 ms per loop