J'ai un dataframe pandas avec des milliers de colonnes et j'aimerais effectuer les opérations suivantes pour chaque colonne du dataframe :

  1. vérifier si la valeur i-ème et i-1-ème valeurs sont dans la plage (entre x et y);
  2. si #1 est satisfait, alors trouvez log(i/i-1) ** 2 de la colonne ;
  3. si #1 n'est pas satisfait, supposez 0 ;
  4. trouver le total de #2 pour chaque colonne.

Voici un dataframe avec une seule colonne :

d = {'col1': [10, 15, 23, 16, 5, 14, 11, 4]}
df = pd.DataFrame(data = d)
df

x = 10 et y = 20

Voici ce que je peux faire pour cette seule colonne :

df["IsIn"] = "NA" 
for i in range(1, len(df.col1)):
    if (x < df.col1[i] < y) & (x < df.col1[i - 1] < y):
        df.IsIn[i] = 1
    else:
        df.IsIn[i] = 0

df["rets"] = np.log(df["col1"] / df["col1"].shift(1))
df["var"] = df["IsIn"] * df["rets"]**2
Total = df["var"].sum()
Total

Idéalement, j'aurais une trame de données (1 par n-cols) de Totals pour chaque colonne. Comment puis-je y parvenir au mieux ? J'apprécierais également si vous pouvez compléter votre réponse avec une explication détaillée.

1
AK88 15 nov. 2020 à 05:50

1 réponse

Meilleure réponse

Oui, c'est une instance où apply fonctionne. Vous n'avez qu'à envelopper votre logique dans une fonction. Considérons également between et shift à condition d'éliminer la première boucle :

def func(s, x=10, y=20):
    '''
    compute the value given a series
    ''' 

    # mask where values are between x and y
    valid = s.between(x,y)

    # shift `valid` and double check
    valid = valid & valid.shift(fill_value=False)

    # squared log, mask with `valid`, and sum
    return (np.log(s/s.shift())**2 * valid).sum()

# apply `func` on the columns
df.apply(func, x=10, y=20)

Production:

col1    0.222561
dtype: float64
1
Quang Hoang 15 nov. 2020 à 03:42