Записать новый датафрейм из предыдущего
Есть df, со столбцами. https://wdho.ru/mqQQ . Как сделать новый датафрейм, в котором строки создаются только по принципу: "Md" не равно предыдущему значению (например "Md"=2, предыдущее =1) - пишем в новую строку new_df = "Date" = 5-Jan-18, "State bef" = 210.35K. И после когда "Md" не будет равно следующему значению (например "Md"=2, следующее =3), допишем в строку еще и "State after" = 269.51K И так со всеми.
"Date" "State bef" "State after" "Md"
2-Jan-18 211.74K 119.34K 1
3-Jan-18 260.86K 81.03K 1
4-Jan-18 246.15K 21.88K 1
5-Jan-18 183.45K 284.02K 1
8-Jan-18 210.35K 226.45K 2
9-Jan-18 319.92K 175.36K 2
10-Jan-18 290.54K 200.58K 2
11-Jan-18 341.94K 228.99K 2
12-Jan-18 302.10K 269.51K 2
15-Jan-18 173.46K 197.06K 3
16-Jan-18 322.95K 228.74K 3
17-Jan-18 280.42K 220.34K 3
18-Jan-18 270.23K 242.75K 3
19-Jan-18 278.36K 298.11K 3
22-Jan-18 250.60K 227.20K 4
23-Jan-18 343.73K 217.16K 4
24-Jan-18 308.37K 249.10K 4
25-Jan-18 301.93K 201.24K 4
26-Jan-18 227.60K 300.69K 4
29-Jan-18 202.24K 199.66K 5
30-Jan-18 135.87K 235.09K 5
31-Jan-18 20.43K 101.08K 5
1-Feb-18 336.92K 179.66K 5
2-Feb-18 307.13K 130.44K 5
5-Feb-18 335.64K 90.22K 6
6-Feb-18 328.85K 25.83K 6
На выходе получается:
df = pd.read_csv('a_red.csv')
2-Jan-18 211.74K 284.02K 1
8-Jan-18 210.35K 269.51K 2
15-Jan-18 173.46K 298.11K 3
22-Jan-18 250.60K 300.69K 4
29-Jan-18 202.24K 130.44K 5
СПАСИБО!
Ответы (3 шт):
Ну элементарно же, если мыслить векторно (что часто требуется при работе с Numpy и Pandas):
import pandas as pd
df = pd.read_csv('a_red.csv')
df.loc[df['"Md"'].diff().fillna(1) > 0]
Берём разницу между значениями колонки Md и отбираем в df только строки, где эта разница есть (т.е. не 0). Ну и ещё из-за того, что в первой строке разница будет NA, надо заполнить это NA значением, например 1, перед проверкой.
Вывод:
"Date" "State bef" "State after" "Md" Unnamed: 4 Unnamed: 5 Unnamed: 6 Unnamed: 7
0 2-Jan-18 211.74K 119.34K 1 NaN NaN NaN
4 8-Jan-18 210.35K 226.45K 2 NaN NaN NaN NaN
9 15-Jan-18 173.46K 197.06K 3 NaN NaN NaN NaN
14 22-Jan-18 250.60K 227.20K 4 NaN NaN NaN NaN
19 29-Jan-18 202.24K 199.66K 5 NaN NaN NaN NaN
24 5-Feb-18 335.64K 90.22K 6 NaN NaN NaN NaN
...
Update: Не заметил сначала условие про "State after", подумаю ещё.
Ну тогда такой вариант, только остаётся ещё заполнить последнее значение в колонке "State after", сейчас там NaN, пока не придумал хороший красивый вариант:
import pandas as pd
df = pd.read_csv('a_red.csv')
df1 = df.copy()
df1['"State after"'] = df['"State after"'].shift(1)
df1 = df1.loc[df['"Md"'].diff(1).fillna(1) > 0]
df1['"State after"'] = df1['"State after"'].shift(-1)
df1
Вывод:
"Date" "State bef" "State after" "Md" Unnamed: 4 Unnamed: 5 Unnamed: 6 Unnamed: 7
0 2-Jan-18 211.74K 284.02K 1 NaN NaN NaN
4 8-Jan-18 210.35K 269.51K 2 NaN NaN NaN NaN
9 15-Jan-18 173.46K 298.11K 3 NaN NaN NaN NaN
14 22-Jan-18 250.60K 300.69K 4 NaN NaN NaN NaN
19 29-Jan-18 202.24K 130.44K 5 NaN NaN NaN NaN
24 5-Feb-18 335.64K 277.12K 6 NaN NaN NaN NaN
Можно так попробовать:
import pandas as pd
df=pd.read_csv("a_red.csv")
res = df.groupby('"Md"').agg({'"Date"': lambda x: x.iloc[0],
'"State bef"': lambda x: x.iloc[0],
'"State after"': lambda x: x.iloc[-1]})
тогда res будет:
"Date" "State bef" "State after"
"Md"
1 2-Jan-18 211.74K 284.02K
2 8-Jan-18 210.35K 269.51K
3 15-Jan-18 173.46K 298.11K
4 22-Jan-18 250.60K 300.69K
5 29-Jan-18 202.24K 130.44K
6 5-Feb-18 335.64K 277.12K
7 12-Feb-18 349.67K 315.27K
8 19-Feb-18 125.63K 275.87K
9 26-Feb-18 188.30K 130.53K
10 5-Mar-18 261.06K 345.22K
11 12-Mar-18 240.03K 319.09K
12 19-Mar-18 272.42K 336.60K
13 26-Mar-18 183.69K 513.72K
14 2-Apr-18 190.05K 115.19K
15 9-Apr-18 257.50K 290.88K
16 16-Apr-18 297.44K 445.04K
17 23-Apr-18 317.45K 417.01K
18 30-Apr-18 24.76K 271.17K
19 7-May-18 230.47K 277.42K
20 14-May-18 290.13K 235.33K
21 21-May-18 245.77K 398.56K
22 28-May-18 65.10K 77.00K
23 4-Jun-18 324.29K 278.36K
24 11-Jun-18 231.28K 300.92K
UPDATE (после уточнений задачи)
Вы можете группировать именно так, как вам нужно следующим образом:
Примерный Df с повторяющимися значениями Md:
"Date" "State bef" "State after" "Md" Unnamed: 4 Unnamed: 5 ...
0 2-Jan-18 211.74K 119.34K 1 NaN NaN
1 3-Jan-18 260.86K 81.03K 1 NaN NaN
2 4-Jan-18 246.15K 21.88K 1 NaN NaN
3 5-Jan-18 183.45K 284.02K 1 NaN NaN
4 8-Jan-18 210.35K 226.45K 2 NaN NaN
5 9-Jan-18 319.92K 175.36K 2 NaN NaN
6 10-Jan-18 290.54K 200.58K 2 NaN NaN
7 11-Jan-18 341.94K 228.99K 2 NaN NaN
8 12-Jan-18 302.10K 269.51K 2 NaN NaN
9 15-Jan-18 173.46K 197.06K 1 NaN NaN
10 16-Jan-18 322.95K 228.74K 1 NaN NaN
11 17-Jan-18 280.42K 220.34K 1 NaN NaN
12 18-Jan-18 270.23K 242.75K 3 NaN NaN
13 19-Jan-18 278.36K 298.11K 3 NaN NaN
14 22-Jan-18 250.60K 227.20K 4 NaN NaN
15 23-Jan-18 343.73K 217.16K 4 NaN NaN
16 24-Jan-18 308.37K 249.10K 4 NaN NaN
17 25-Jan-18 301.93K 201.24K 4 NaN NaN
18 26-Jan-18 227.60K 300.69K 4 NaN NaN
19 29-Jan-18 202.24K 199.66K 2 NaN NaN
20 30-Jan-18 135.87K 235.09K 2 NaN NaN
Тогда:
res = df.groupby([(df['"Md"'] != df['"Md"'].shift()).cumsum()]).agg({'"Date"': lambda x: x.iloc[0],
'"State bef"': lambda x: x.iloc[0],
'"State after"': lambda x: x.iloc[-1]})
даст нам res:
"Date" "State bef" "State after"
"Md"
1 2-Jan-18 211.74K 284.02K
2 8-Jan-18 210.35K 269.51K
3 15-Jan-18 173.46K 220.34K
4 18-Jan-18 270.23K 298.11K
5 22-Jan-18 250.60K 300.69K
6 29-Jan-18 202.24K 235.09K
Вот такая программулька:
import pandas as pd
df = pd.read_csv('~/tmp/a_red.csv', sep=',')
df_new = pd.DataFrame(df.iloc[0])
for row in range(1, df.shape[0]-1):
if df.iloc[row]['"Md"'] != df.iloc[row-1]['"Md"']:
df_new.append(df.iloc[row], ignore_index=True)
print (row, ') ', df.iloc[row]['"Date"'], df.iloc[row]['"State bef"'], df.iloc[row]['"State after"'], df.iloc[row]['"Md"'])
Выдаёт такую подборку данных:
4 ) 8-Jan-18 210.35K 226.45K 2
9 ) 15-Jan-18 173.46K 197.06K 3
14 ) 22-Jan-18 250.60K 227.20K 4
19 ) 29-Jan-18 202.24K 199.66K 5
24 ) 5-Feb-18 335.64K 90.22K 6
29 ) 12-Feb-18 349.67K 274.79K 7
34 ) 19-Feb-18 125.63K 298.14K 8
39 ) 26-Feb-18 188.30K 300.16K 9
44 ) 5-Mar-18 261.06K 124.00K 10
49 ) 12-Mar-18 240.03K 361.25K 11
54 ) 19-Mar-18 272.42K 482.51K 12
59 ) 26-Mar-18 183.69K 359.01K 13
63 ) 2-Apr-18 190.05K 366.65K 14
68 ) 9-Apr-18 257.50K 34.70K 15
73 ) 16-Apr-18 297.44K 361.36K 16
78 ) 23-Apr-18 317.45K 379.72K 17
83 ) 30-Apr-18 24.76K 334.98K 18
88 ) 7-May-18 230.47K 150.81K 19
93 ) 14-May-18 290.13K 256.24K 20
98 ) 21-May-18 245.77K 246.92K 21
103 ) 28-May-18 65.10K 319.37K 22
108 ) 4-Jun-18 324.29K 102.59K 23
113 ) 11-Jun-18 231.28K 321.11K 24
Первая строка df_new не распечатывается, так как она вставляется сразу же, до цикла.