У меня есть dataFrame с именами и типами. Мне нужно создать "newType" -column, используя shift для столбца "Тип". Мои данные:
ind name Type
____________________
1 sasha a
2 sasha e
3 sasha d
4 sasha t
5 sasha t
6 sasha w
7 nik e
8 nik e
9 nik q
10 nik t
11 nik h
12 nik j
13 bob k
14 bob y
15 bob r
16 bob w
17 bob t
18 bob w
Мне нужно создать новый столбец, используя window = n для "Тип" -column с условием "name" -column. Если строки в моем окне имеют разные имена, мы возвращаем NaN.
размер окна = 3, окно выглядит так
[Тип [i-1], Тип [i], Тип [i + 1]]
размер = 4
[Тип [i-2], Тип [i-1], Тип [i], Тип [i + 1]]
размер = 5
[Тип [i-3], Тип [i-2], Тип [i-1], Тип [i], Тип [i + 1]]
...так далее
Иллюстрация для окна = 4: Изображение: визуализация алгоритма
Результат, который мне нужен:
ind name Type newType
____________________________
1 sasha a NaN
2 sasha e NaN
3 sasha d aedt
4 sasha t edtt
5 sasha t dttw
6 sasha w NaN
7 nik e NaN
8 nik e NaN
9 nik q eeqt
10 nik t eqth
11 nik h qthj
12 nik j NaN
13 bob k NaN
14 bob y NaN
15 bob r kyrw
16 bob w yrwt
17 bob t rwtw
18 bob w NaN
Как это сделать?
Это, вероятно, не выполняется наиболее эффективным способом, но опять же это несколько сложная операция. Я некоторое время пытался использовать функции катания или расширения, но безуспешно (поскольку они, похоже, работают только с численными аргументами). Вот мой метод для достижения желаемого результата:
from io import StringIO
import pandas as pd
import numpy as np
# Make DataFrame
df = pd.read_table(StringIO("""ind name Type
1 sasha a
2 sasha e
3 sasha d
4 sasha t
5 sasha t
6 sasha w
7 nik e
8 nik e
9 nik q
10 nik t
11 nik h
12 nik j
13 bob k
14 bob y
15 bob r
16 bob w
17 bob t
18 bob w"""), sep='\s+')
def joiner(r):
return "-".join(r.values)
df.set_index('name', inplace=True)
# Make new column which join letters aggregated by name
df['full_join'] = df.groupby('name')['Type'].apply(joiner)
df['full_join'].ffill(inplace=True)
df.reset_index(inplace=True)
a = df.full_join.str.split("-",expand=True)
b = []
w = 4 # window
# This part is probably not as efficient as it could be
for i in range(len(a)):
j = i % len(a.iloc[i].str.split('-'))
b.append("".join(a.iloc[i,j-(w-1):j+1].tolist()))
df['result'] = b
df['result'] = df['result'].shift(-1)
df.loc[df['result'] == "", 'result'] = np.nan
df.drop(columns=['full_join'], inplace=True)
Результат:
Out[135]:
name ind Type result
0 sasha 1 a NaN
1 sasha 2 e NaN
2 sasha 3 d aedt
3 sasha 4 t edtt
4 sasha 5 t dttw
5 sasha 6 w NaN
6 nik 7 e NaN
7 nik 8 e NaN
8 nik 9 q eeqt
9 nik 10 t eqth
10 nik 11 h qthj
11 nik 12 j NaN
12 bob 13 k NaN
13 bob 14 y NaN
14 bob 15 r kyrw
15 bob 16 w yrwt
16 bob 17 t rwtw
17 bob 18 w NaN
Приятно удивил, что это закончилось тем же успехом и для других окон (я тестировал 2, 3 и 5). К сожалению, при добавлении строки в nik :(