0
votes

Comment créer une nouvelle colonne en fonction d'autres lignes de Pandas Dataframe?

J'ai une trame de données avec des rangées de 200K et j'essaie d'ajouter des colonnes en fonction d'autres lignes avec certaines conditions. J'ai essayé de l'atteindre mais prenez beaucoup de temps (2 heures).

Voici mon code: P>

   A_id  B_id     C_date   D   E  D_mean  E_mean
0     1    10 2019-02-22  10   7     NaN     NaN
1     2    20 2019-02-28  12  10     NaN     NaN
2     1    10 2019-07-03  21  14    10.0     7.0
3     2    20 2019-03-14  81  31    12.0    10.0
4     1    10 2019-12-21  20  61    15.5    10.5
5     2    20 2019-11-10   1   9    46.5    20.5


0 commentaires

3 Réponses :


3
votes

Nous pouvons utiliser une combinaison de fonctions pour y parvenir, la plus notable que le pd.dataframe.rolling code> pour calculer la moyenne mobile.

def custom_agg(group):
    cols = ['D', 'E']
    for col in cols:
        name = '{}_mean'.format(col)
        group[name] = group[col].shift() \
                                .rolling(len(group[col]), min_periods=2) \
                                .mean() \
                                .fillna(group[col].iloc[0])
        group[name].iloc[0] = pd.np.nan
    return group

dataset.groupby(['A_id', 'B_id'], as_index=False).apply(custom_agg)

   A_id  B_id     C_date   D   E  D_mean  E_mean
0     1    10 2019-02-22  10   7     NaN     NaN
1     2    20 2019-02-28  12  10     NaN     NaN
2     1    10 2019-07-03  21  14    10.0     7.0
3     2    20 2019-03-14  81  31    12.0    10.0
4     1    10 2019-12-21  20  61    15.5    10.5
5     2    20 2019-11-10   1   9    46.5    20.5


1 commentaires

Cela a fonctionné pour moi. Votre solution est 7 fois plus rapide que la mienne. Merci



0
votes

J'ai soupçonné que votre création de sous-ensemble dans la boucle était chère et que mes tests ont révélé que votre algorithme fonctionnait à environ 11 000 indices par minute. J'ai proposé un algorithme alternatif qui pré-trie les données de sorte que le calcul du sous-ensemble devienne trivial et s'exécutant sur un ensemble de données de données de 200K de données aléatoires prend moins de 5 minutes.

dataset.sort_values(by=['A_id', 'B_id', 'C_date'], inplace=True)
dataset.reset_index(drop=True, inplace=True)

last_A = None
last_B = None
first_index = -1
for index in dataset.index:
    A_id = dataset.loc[index, 'A_id']
    B_id = dataset.loc[index, 'B_id']
    C_date = dataset.loc[index, 'C_date']

    if (last_A != A_id) | (last_B != B_id):
        first_index = index
        last_A = A_id
        last_B = B_id

    subset = dataset[first_index:index]
    dataset.at[index, 'D_mean'] = subset['D'].mean()
    dataset.at[index, 'E_mean'] = subset['E'].mean()


3 commentaires

itération sur chaque rangée dans un fichier de données n'est pas un optimal ou idéal solution


Je n'étais pas au courant de la fonction applicable. Je retrouverai ma solution pour utiliser cela.


L'utilisation simplement appliquer est la même que celle itérante sur chaque ligne, l'objectif ultime des pandas est d'utiliser leurs fonctions intégrées vectorisées.



0
votes

Voici une seule façon de faire en utilisant .apply : xxx


0 commentaires