Разрезать фрейм данных на сегменты по разнице от первого ряда в сегменте - PullRequest
0 голосов
/ 17 октября 2019
.      col_0          col_1          col_3
0  57342  122877889  25.524446
1  57343  122878889  25.527077
2  57344  122879889  26.582283
3  57345  122880889  27.594110
4  57346  122881889  28.612511
5  57347  122882889  28.517876
6  57348  122883889  29.521818
7  57349  122884889  28.517876
8  57350  122885889  28.473185
9  57351  122886889  28.483698

У меня есть датафрейм, как указано выше. (Со многими другими строками).

Я хотел бы разбить фрейм данных следующим образом:

Each group's col_3 values have a distance of 2 or less from the group's first row's col_3 value. (So if row 0 has a col_3 of 25.0, all the members of that group have col_3 values in the range 22.0 to 27.0)

For the first row which does not meet that criteria, that row becomes a new group.

Таким образом, фрейм данных выше будет сгруппирован в строки [0–2] истроки [от 3 до 9].

Таким образом, на выходе могут быть два кадра данных:

.      col_0          col_1          col_3
0  57342  122877889  25.524446
1  57343  122878889  25.527077
2  57344  122879889  26.582283

и

.      col_0          col_1          col_3    
3  57345  122880889  27.594110
4  57346  122881889  28.612511
5  57347  122882889  28.517876
6  57348  122883889  29.521818
7  57349  122884889  28.517876
8  57350  122885889  28.473185
9  57351  122886889  28.483698

Или только значения [0,3] (начало каждой ячейки).

Как я могу это сделать, кроме как циклически проходить по фрейму данных построчно? Это то, что cut может сделать?

Ответы [ 3 ]

1 голос
/ 17 октября 2019

Вот как вы можете сделать это, используя цифровую трансляцию и цикл, пожалуйста, найдите описание в комментарии в коде

## dummy data
df = pd.DataFrame([['57342', '122877889', 25.524446], ['57343', '122878889', 25.527077], ['57344', '122879889', 26.582283], ['57345', '122880889', 27.59411], ['57346', '122881889', 28.612511], ['57347', '122882889', 28.517876], ['57348', '122883889', 29.521818], ['57349', '122884889', 29.517876], ['57350', '122885889', 32.473185], ['57351', '122886889', 32.483698]], columns=('col_0', 'col_1', 'col_3'))

## use numpy broadcast to find difference between each pair of numbers
## result will be matrix with each cell representing difference of pair
diff = np.abs(df["col_3"].values - df["col_3"].values[:, np.newaxis])
distance_gt2 = (diff>2).astype(int)
print(distance_gt2)
## loop though the matrix and find contigious block where difference is <= 2
j=1
segments=[]
for i in range(len(df)):
    s = np.sum(distance_gt2[j:i,j:i])
    ## when is sum is greater that 0 that is next segment
    if s>0:
        segments.append(df[j-1:i-1])
        j=i

segments.append(df[j-1:len(df)])  

[print(segment) for segment in segments]

Обратите внимание на непрерывный блок нулей, которые указывают расстояние менее 2

## print(distance_gt2)
[[0 0 0 1 1 1 1 1 1 1]
 [0 0 0 1 1 1 1 1 1 1]
 [0 0 0 0 1 0 1 1 1 1]
 [1 1 0 0 0 0 0 0 1 1]
 [1 1 1 0 0 0 0 0 1 1]
 [1 1 0 0 0 0 0 0 1 1]
 [1 1 1 0 0 0 0 0 1 1]
 [1 1 1 0 0 0 0 0 1 1]
 [1 1 1 1 1 1 1 1 0 0]
 [1 1 1 1 1 1 1 1 0 0]]

Результат

   col_0      col_1      col_3
0  57342  122877889  25.524446
1  57343  122878889  25.527077
2  57344  122879889  26.582283

   col_0      col_1      col_3
3  57345  122880889  27.594110
4  57346  122881889  28.612511
5  57347  122882889  28.517876
6  57348  122883889  29.521818
7  57349  122884889  29.517876

   col_0      col_1      col_3
8  57350  122885889  32.473185
9  57351  122886889  32.483698
1 голос
/ 17 октября 2019

Вы можете использовать функцию ниже

df_list=[]
def func(df):
    ind=0
    i=1    
    while len(df)!=0:
        val_diff= df['col_3'].apply(lambda x:x >= (df['col_3']+2))
        ind = val_diff[0].idxmax()
        if ind !=0:
            globals()["df"+str(i)]=df.loc[0:ind-1,]
            df=df.loc[ind:,].reset_index(drop=True)
            df_list.append("df"+str(i))
        else:
            globals()["df"+str(i)]=df.loc[ind:,]
            df=df.loc[0:ind-1,]
            df_list.append("df"+str(i))
        i=i+1
        if len(df)==0:
            break

Вызовите эту функцию на вашем фрейме данных func(your_df), если вы сделаете print(df_list), вы должны получить список фреймов данных, которые были созданы этой функцией.

Затем вы можете вызвать каждый из этих фреймов данных.

0 голосов
/ 17 октября 2019

Это работает, если вам не требуется новая группа, когда значения возвращаются к предыдущему диапазону. Это сокращает основанный на диапазоне минимальных и максимальных значений в col3 с шагом 5 и группирует корзины. Затем вы можете захватить каждую отдельную группу, когда это необходимо.

group = df.groupby(
    pd.cut(
        df['col_3'],
        np.arange(
            np.floor(df.col_3.iloc[0]) - 2,
            np.floor(df.col_3.iloc[-1]) + 6, 5)))

keys = list(group.groups.keys())

print(group.get_group(keys[0]))
print(group.get_group(keys[1]))
   col_0      col_1      col_3
0  57342  122877889  25.524446
1  57343  122878889  25.527077
2  57344  122879889  26.582283
3  57345  122880889  27.594110
   col_0      col_1      col_3
4  57346  122881889  28.612511
5  57347  122882889  28.517876
6  57348  122883889  29.521818
7  57349  122884889  28.517876
8  57350  122885889  28.473185
9  57351  122886889  28.483698
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...