Дублируйте последнюю строку со значением, индексом и слиянием - PullRequest
0 голосов
/ 26 марта 2020

У меня есть этот фрейм данных:

ID  X1  X2  X3   Y
 A   9   2   3  10
 A   3   5   5   0
 A   3   3   4   0
 A   6   3   6  20
 A   6   7   4   0
 A   2   4   9   0
 A   1   7   8   0
 B   6   9   5   0
 B   3   3   7  10
 B   6   7   8  20
 B   5   2   7   0
 B   2   9   3  10
 B   7   2   7   0
 B   9   2   6   0
 C   2   9   4  30
 C   5   1   5  40
 C   8   3   2   0
 C   2   1   9  40
 C   3   9   8  30
 C   7   9   6  20
 D   8   2   6  10
 D   3   1   8   0
 D   4   8   9  20
 D   7   3   2  10
 F   2   8   8   0
 F   7   4   8   0

Шаг # 1:

Сначала дублируйте последнюю строку, для каждого идентификатора (groupby('ID')), пропуск 0 значений в столбце Y.

Затем индексировать строки (по df['index'] = df.index).

После шага № 1 df должен выглядеть следующим образом:

 index ID  X1  X2  X3   Y
     1  A   9   2   3  10
     2  A   3   5   5   0
     3  A   3   3   4   0
     4  A   6   3   6  20
     5  A   6   7   4   0
     6  A   2   4   9   0
     7  A   1   7   8   0
     8  A   6   3   6  20
     9  B   6   9   5   0
    10  B   3   3   7  10
    11  B   6   7   8  20
    12  B   5   2   7   0
    13  B   2   9   3  10
    14  B   7   2   7   0
    15  B   9   2   6   0
    16  B   2   9   3  10
    17  C   2   9   4  30
    18  C   5   1   5  40
    19  C   8   3   2   0
    20  C   2   1   9  40
    21  C   3   9   8  30
    22  C   7   9   6  20
    23  C   7   9   6  20
    24  D   8   2   6  10
    25  D   3   1   8   0
    26  D   4   8   9  20
    27  D   7   3   2  10
    28  D   7   3   2  10
    29  F   2   8   8   0
    30  F   7   4   8   0 

Шаг № 2:

Сначала исключите тех, у кого в столбце 0 в Y (df2 = df[df['Y'] != 0]).

Затем создать столбец X4 (независимо от того, какие значения назначить. В этом примере я назначаю 1 для всех строк в этом X4 на df2['X4'] = np.ones(len(df2))).

  • Примечание. Фактически на этом шаге я создаю некоторую другую переменную с вычислениями, но это не имеет значения для примера.

После шага № 2 df2 должен выглядеть следующим образом:

 index ID  X1  X2  X3  X4   Y
     1  A   9   2   3   1  10
     4  A   6   3   6   1  20
     8  A   6   3   6   1  20
    10  B   3   3   7   1  10
    11  B   6   7   8   1  20
    13  B   2   9   3   1  10
    16  B   2   9   3   1  10
    17  C   2   9   4   1  30
    18  C   5   1   5   1  40
    20  C   2   1   9   1  40
    21  C   3   9   8   1  30
    22  C   7   9   6   1  20
    23  C   7   9   6   1  20
    24  D   8   2   6   1  10
    26  D   4   8   9   1  20
    27  D   7   3   2   1  10
    28  D   7   3   2   1  10

Шаг № 3:

Сначала объедините df с df2, index (df = df.merge(df2, on = 'index', how = 'left')).

Затем исключите последнюю добавленную нами строку, для каждого идентификатора .

Окончательный результат (df):

 index ID  X1  X2  X3   X4   Y
     1  A   9   2   3  1.0  10
     2  A   3   5   5  NaN   0
     3  A   3   3   4  NaN   0
     4  A   6   3   6  1.0  20
     5  A   6   7   4  NaN   0
     6  A   2   4   9  NaN   0
     7  A   1   7   8  NaN   0
     9  B   6   9   5  NaN   0
    10  B   3   3   7  1.0  10
    11  B   6   7   8  1.0  20
    12  B   5   2   7  NaN   0
    13  B   2   9   3  1.0  10
    14  B   7   2   7  NaN   0
    15  B   9   2   6  NaN   0
    17  C   2   9   4  1.0  30
    18  C   5   1   5  1.0  40
    19  C   8   3   2  NaN   0
    20  C   2   1   9  1.0  40
    21  C   3   9   8  1.0  30
    22  C   7   9   6  1.0  20
    24  D   8   2   6  1.0  10
    25  D   3   1   8  NaN   0
    26  D   4   8   9  1.0  20
    27  D   7   3   2  1.0  10
    28  D   7   3   2  1.0  10
    29  F   2   8   8  NaN   0
    30  F   7   4   8  NaN   0

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

1 Ответ

1 голос
/ 26 марта 2020

Идея состоит в том, чтобы удалить 0 значения на Y, а затем дублировать на ID до df1, но для правильного упорядочения используется карта по значениям индекса + 0.5, поэтому после concat и DataFrame.sort_index для правильного порядка:

#df['index'] = df.index + 1

idx = df.drop_duplicates('ID', keep='last')['ID']
idx = pd.Series(idx.index + .5, idx)
#print (idx)

df1 = df[df['Y'].ne(0)].drop_duplicates('ID', keep='last')
df1.index = df1['ID'].map(idx)
df = pd.concat([df, df1]).sort_index().reset_index(drop=True)
df['index'] = np.arange(1, len(df)+1)

df2 = df[df['Y'] != 0].copy()
df2['X4'] = 1
#print (df2)
df = df.merge(df2[['index','X4']], on = 'index', how = 'left')

Последний отфильтровывает последние дублированные значения на ID, если X2 не NaN:

df = df[df['ID'].duplicated(keep='last') | df['X4'].isna()]
print (df)
   ID  X1  X2  X3   Y  index   X4
0   A   9   2   3  10      1  1.0
1   A   3   5   5   0      2  NaN
2   A   3   3   4   0      3  NaN
3   A   6   3   6  20      4  1.0
4   A   6   7   4   0      5  NaN
5   A   2   4   9   0      6  NaN
6   A   1   7   8   0      7  NaN
8   B   6   9   5   0      9  NaN
9   B   3   3   7  10     10  1.0
10  B   6   7   8  20     11  1.0
11  B   5   2   7   0     12  NaN
12  B   2   9   3  10     13  1.0
13  B   7   2   7   0     14  NaN
14  B   9   2   6   0     15  NaN
16  C   2   9   4  30     17  1.0
17  C   5   1   5  40     18  1.0
18  C   8   3   2   0     19  NaN
19  C   2   1   9  40     20  1.0
20  C   3   9   8  30     21  1.0
21  C   7   9   6  20     22  1.0
23  D   8   2   6  10     24  1.0
24  D   3   1   8   0     25  NaN
25  D   4   8   9  20     26  1.0
26  D   7   3   2  10     27  1.0
28  F   2   8   8   0     29  NaN
29  F   7   4   8   0     30  NaN

РЕДАКТИРОВАТЬ:

Еще одна идея для appenf последней строки:

def f(x):
    y = x[x['Y'].ne(0)].tail(1)
    return x.append(y)

df = df.groupby('ID').apply(f)
print (df)
      ID  X1  X2  X3   Y
ID                      
A  0   A   9   2   3  10
   1   A   3   5   5   0
   2   A   3   3   4   0
   3   A   6   3   6  20
   4   A   6   7   4   0
   5   A   2   4   9   0
   6   A   1   7   8   0
   3   A   6   3   6  20
B  7   B   6   9   5   0
   8   B   3   3   7  10
   9   B   6   7   8  20
   10  B   5   2   7   0
   11  B   2   9   3  10
   12  B   7   2   7   0
   13  B   9   2   6   0
   11  B   2   9   3  10
C  14  C   2   9   4  30
   15  C   5   1   5  40
   16  C   8   3   2   0
   17  C   2   1   9  40
   18  C   3   9   8  30
   19  C   7   9   6  20
   19  C   7   9   6  20
D  20  D   8   2   6  10
   21  D   3   1   8   0
   22  D   4   8   9  20
   23  D   7   3   2  10
   23  D   7   3   2  10
F  24  F   2   8   8   0
   25  F   7   4   8   0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...