J'ai un bloc de données suivant df avec deux colonnes "identifiant", "valeurs" et "subid":
identifier values subid
0 1 101 1
1 1 102 1
2 1 103 2 #index in list x
3 1 104 2
4 1 105 2
5 2 106 3
6 2 107 3
7 2 108 3
8 2 109 4 #index in list x
9 2 110 4
10 3 111 5
11 3 112 5
12 3 113 6 #index in list x
J'ai une liste d'indices, disons
x = [2, 8, 12]
Je veux insérer des lignes juste avant les indices mentionnés dans la liste x. Comme pour la ligne insérée juste avant l’index 2, les valeurs suivantes seront attribuées: même identificateur que la ligne de l’index 2, c’est-à-dire 1; mêmes valeurs que la ligne d'index 2, c'est-à-dire 103; mais le subid dans la nouvelle ligne serait ((subid à l'index 2) - 1), ou simplement le subid de la ligne précédente, c'est-à-dire 1.
Vous trouverez ci-dessous le résultat final attendu:
identifier values subid
0 1 101 1
1 1 102 1
2 1 103 1 #new row inserted
3 1 103 2 #index in list x
4 1 104 2
5 1 105 2
6 2 106 3
7 2 107 3
8 2 108 3
9 2 109 3 #new row inserted
10 2 109 4 #index in list x
11 2 110 4
12 3 111 5
13 3 112 5
14 3 113 5 #new row inserted
15 3 113 6 #index in list x
Le code que j'ai essayé:
m = df.index #storing the indices of the df
#m
for i in m:
if i in x: #x is the given list of indices
df.iloc[i-1]["identifier"] = df.iloc[i]["identifier"]
df.iloc[i-1]["values"] = df.iloc[i]["values"]
df.iloc[i-1]["subid"] = (df.iloc[i]["subid"]-1)
df
Le code ci-dessus est simplement remplacer les lignes à (i-1) indices et ne pas insérer les lignes supplémentaires avec les valeurs ci-dessus. S'il vous plaît aider.
S'il vous plaît laissez-moi savoir si quelque chose n'est pas clair.
Préserver l'ordre des index est la partie la plus délicate. Je ne suis pas sûr que ce soit le moyen le plus efficace de le faire, mais cela devrait fonctionner.
x = [2,8,12]
rows = []
cur = {}
for i in df.index:
if i in x:
cur['index'] = i
cur['identifier'] = df.iloc[i].identifier
cur['values'] = df.iloc[i]['values']
cur['subid'] = df.iloc[i].subid - 1
rows.append(cur)
cur = {}
Ensuite, parcourez la nouvelle liste de lignes et effectuez un concaténage incrémentiel en insérant chaque nouvelle ligne à l'emplacement approprié.
offset = 0; #tracks the number of rows already inserted to ensure rows are inserted in the correct position
for d in rows:
df = pd.concat([df.head(d['index'] + offset), pd.DataFrame([d]), df.tail(len(df) - (d['index']+offset))])
offset+=1
df.reset_index(inplace=True)
df.drop('index', axis=1, inplace=True)
df
level_0 identifier subid values
0 0 1 1 101
1 1 1 1 102
2 0 1 1 103
3 2 1 2 103
4 3 1 2 104
5 4 1 2 105
6 5 2 3 106
7 6 2 3 107
8 7 2 3 108
9 0 2 3 109
10 8 2 4 109
11 9 2 4 110
12 10 3 5 111
13 11 3 5 112
14 0 3 5 113
15 12 3 6 113
soustraire où la ligne précédente est différente de la ligne actuelle
# edit in place
df['values'] -= df.identifier.ne(df.identifier.shift().bfill())
df
identifier values
0 1 101
1 1 102
2 1 103
3 1 104
4 1 105
5 2 105
6 2 107
7 2 108
8 2 109
9 2 110
10 3 110
11 3 112
12 3 113
Ou
# new dataframe
df.assign(values=df['values'] - df.identifier.ne(df.identifier.shift().bfill()))
identifier values
0 1 101
1 1 102
2 1 103
3 1 104
4 1 105
5 2 105
6 2 107
7 2 108
8 2 109
9 2 110
10 3 110
11 3 112
12 3 113