Mam serię Pandas zawierające zera i te:

df1 = pd.Series([ 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0])
df1
Out[3]: 
0         0
1         0
2         0
3         0
4         0
5         1
6         1
7         1
8         0
9         0
10        0

Chciałbym utworzyć dataframe DF2, który zawiera początek i koniec interwałów o tej samej wartości, wraz z wartością powiązaną ... DF2 w tym przypadku powinien być ...

df2
Out[5]: 
   Start     End  Value
0      0  4         0
1      5  7         1
2      8  10        0

Moją próbą było:

from operator import itemgetter
from itertools import groupby

a=[next(group) for key, group in groupby(enumerate(df1), key=itemgetter(1))]   
df2 = pd.DataFrame(a,columns=['Start','Value'])

Ale nie wiem, jak uzyskać indeksy "End"

2
gabboshow 28 czerwiec 2017, 12:06

4 odpowiedzi

Najlepsza odpowiedź

Możesz {X0}} {{X1}. }} przesunięte {x4}} df1 przez {X5}}.

Następnie apply funkcja Custum i ostatnia zmiana przekształcania {{X1} }.

s = df1.ne(df1.shift()).cumsum()
df2 = df1.groupby(s).apply(lambda x: pd.Series([x.index[0], x.index[-1], x.iat[0]], 
                                                index=['Start','End','Value']))
                   .unstack().reset_index(drop=True)
print (df2)
   Start  End  Value
0      0    4      0
1      5    7      1
2      8   10      0

Kolejne rozwiązanie z agregacją przez {{X0 }} z first i last, ale konieczne jest więcej kodu do przesyłania wyjścia przez żądane wyjście.

s = df1.ne(df1.shift()).cumsum()
d = {'first':'Start','last':'End'}
df2 = df1.reset_index(name='Value') \
         .groupby([s, 'Value'])['index'] \
         .agg(['first','last'])  \
         .reset_index(level=0, drop=True) \
         .reset_index() \
         .rename(columns=d) \
         .reindex_axis(['Start','End','Value'], axis=1)
print (df2)
   Start  End  Value
0      0    4      0
1      5    7      1
2      8   10      0
0
jezrael 28 czerwiec 2017, 11:58

Możesz zbliżyć się za pomocą Shift and Cummum i znajdź pierwszy i ostatni ważny indeks

df2 = df1.groupby((df1 != df1.shift()).cumsum()).apply(lambda x: np.ravel([x.index[0], x.index[-1], x.unique()]))
df2 = pd.DataFrame(df2.values.tolist()).rename(columns = {0: 'Start', 1: 'End',2:'Value'})

Dostajesz

    Start   End     Value
0   0       4       0
1   5       7       1
2   8       10      0
0
Vaishali 28 czerwiec 2017, 11:10

Szukasz, że szukasz, jest Uzyskaj pierwsze i ostatnie wartości w Groupby.

import pandas as pd

def first_last(df):
    return df.ix[[0,-1]]

df = pd.DataFrame([3]*4+[4]*4+[1]*4+[3]*3,columns=['value'])
print df
df['block'] = (df.value.shift(1) != df.value).astype(int).cumsum()
df = df.reset_index().groupby(['block','value'])['index'].agg(['first', 'last']).reset_index()
del df['block']
print df
0
Hardik Sondagar 28 czerwiec 2017, 09:49

Możesz użyć metody pd.Series.diff(), aby zidentyfikować indeksy początkowe:

df2 = pd.DataFrame()
df2['Start'] = df1[df1.diff().fillna(1) != 0].index

Następnie oblicz wskaźniki końcowe z tego:

df2['End'] = [e - 1 for e in df2['Start'][1:]] + [df1.index.max()]

I wreszcie zebrać powiązane wartości:

df2['Value'] = df1[df2['Start']].values

Wynik

   Start  End  Value
0      0    4      0
1      5    7      1
2      8   10      0
0
Archeo 28 czerwiec 2017, 09:43