1
votes

Comment générer des données synthétiques avec des valeurs aléatoires sur le dataframe pandas?

J'ai un dataframe avec 50K lignes. Je voudrais remplacer 20% des données par des valeurs aléatoires (donnant un intervalle de nombres aléatoires). Le but est de générer des valeurs aberrantes synthétiques pour tester les algorithmes. Le dataframe suivant est une petite partie de df que j'ai. Les valeurs qui doivent être remplacées par des valeurs aberrantes aléatoires sont la colonne «valeur».

        date      time  value
0  2016-11-10  22:00:00     90
1  2016-11-10  23:00:00     91
2  2016-11-11  00:00:00     80
3  2016-11-11  01:00:00     4
4  2016-11-11  02:00:00     84
5  2016-11-11  03:00:00     94
6  2016-11-11  04:00:00     32
7  2016-11-11  05:00:00     94

Par exemple, je veux donner un intervalle de valeurs aléatoires de 1 à 50, et le df souhaité ressemblerait à comme suit:

import pandas as pd
dict = {'date':["2016-11-10", "2016-11-10", "2016-11-11", "2016-11-11","2016-11-11","2016-11-11","2016-11-11", "2016-11-11" ], 
        'time': ["22:00:00", "23:00:00", "00:00:00", "01:00:00", "02:00:00", "03:00:00", "04:00:00", "04:00:00"], 
        'value':[90, 91, 80, 87, 84,94, 91, 94]} 

df = pd.DataFrame(dict) 

print(df)
        date      time  value
0  2016-11-10  22:00:00     90
1  2016-11-10  23:00:00     91
2  2016-11-11  00:00:00     80
3  2016-11-11  01:00:00     87
4  2016-11-11  02:00:00     84
5  2016-11-11  03:00:00     94
6  2016-11-11  04:00:00     91
7  2016-11-11  05:00:00     94

J'apprécierais toutes les idées. Merci!


3 commentaires

Si je vous comprends bien, voulez-vous remplacer 20% des valeurs de la colonne "valeur" par des valeurs aléatoires comprises entre 1 et 50?


Oui. ou à plusieurs intervalles si c'est possible par exemple de 1 à 50 et de 200 à 300. Est-il possible de le faire automatiquement?


L'utilisation de "dict" comme nom de variable n'est pas suggérée car il s'agit d'un nom intégré représentant un dictionnaire


5 Réponses :


-1
votes

Voici quelques étapes que vous pouvez utiliser. Comme indiqué ci-dessus, vous ne devez PAS utiliser dict comme nom de variable. Je l'ai fait ci-dessous, car je viens de copier vos entrées de code.

Ce code génère une liste d'indices en fonction du taux de remplacement et de la longueur de la trame de données, puis remplace les valeurs à ces emplacements par des entiers aléatoires uniformes de 0 à 20, inclusivement:

In [49]: # %load 32-36 
    ...: df=pd.DataFrame(dict) 
    ...: import random 
    ...: replacement_ratio = 0.50 
    ...: replacement_count = int(replacement_ratio * len(df)) 
    ...: replacement_idx = random.sample(range(len(df)), replacement_count)            

In [50]: replacement_idx                                                              
Out[50]: [5, 2, 7, 6]

In [51]: for idx in replacement_idx: 
    ...:     df.loc[idx, 'value'] = random.randint(0,20) 
    ...:                                                                              

In [52]: df                                                                           
Out[52]: 
         date      time  value
0  2016-11-10  22:00:00     90
1  2016-11-10  23:00:00     91
2  2016-11-11  00:00:00      4
3  2016-11-11  01:00:00     87
4  2016-11-11  02:00:00     84
5  2016-11-11  03:00:00      4
6  2016-11-11  04:00:00     17
7  2016-11-11  04:00:00      8

In [53]: 


0 commentaires

0
votes

Cela pourrait fonctionner.

outliers = []
def get_outlier(x):
    num = 3
    mean_ = np.mean(x)
    std_ = np.std(x)
    for y in x:
        z_score = (y - mean_) / std_
        if np.abs(z_score) > num:
            outliers.append(y)
    return get_outlier

detect_outliers = get_outlier(df['value'])
sorted(df['value'])
q1, q3 = np.percentile(df['value'], [25, 75])
iqr = q3 - q1
lb = q1 - (1.5 * iqr)
ub = q3 - (1.5 * iqr)

for i in range(len(df)):
    if ((df['value'][i] < lb) | (df['value'][i] > ub)):
        df['value'][i] = np.random.randint(1, 50)


0 commentaires

1
votes

Voici un exemple de numpy qui devrait être rapide. L'exemple qui inclut à la fois le remplacement supérieur et inférieur suppose que vous souhaitez remplacer les valeurs haute et basse de manière égale (50-50) si ce n'est pas le cas, vous pouvez modifier le p dans mask_high = np.random.choice ([0,1], p = [. 5, .5], size = rand.shape) .astype (np.bool) à ce que vous voulez.

%%timeit
myFunc2(df, .2, 1, 50, 200, 300, 'value')

493 µs ± 41.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


0 commentaires

0
votes

Une autre tentative, en utilisant DataFrame.sample () .

         date      time  value
0  2016-11-10  22:00:00     31   <-- 31
1  2016-11-10  23:00:00     91
2  2016-11-11  00:00:00     80
3  2016-11-11  01:00:00     87
4  2016-11-11  02:00:00     84
5  2016-11-11  03:00:00    236   <-- 236
6  2016-11-11  04:00:00     91
7  2016-11-11  04:00:00     94

Ceci imprime (par exemple):

import numpy as np
import pandas as pd

d = {'date':["2016-11-10", "2016-11-10", "2016-11-11", "2016-11-11","2016-11-11","2016-11-11","2016-11-11", "2016-11-11" ],
     'time': ["22:00:00", "23:00:00", "00:00:00", "01:00:00", "02:00:00", "03:00:00", "04:00:00", "04:00:00"],
     'value':[90, 91, 80, 87, 84,94, 91, 94]}

df = pd.DataFrame(d)

random_rows = df.sample(frac=.2)    # 20% random rows from `df`

# we are replacing these 20% random rows with values from 1..50 and 200..300 (in ~1:1 ratio)
random_values = np.random.choice( np.concatenate( [np.random.randint(1, 50, size=len(random_rows) // 2 + 1),
                                                   np.random.randint(200, 300, size=len(random_rows) // 2 + 1)] ),
                size=len(random_rows) )
df.loc[random_rows.index, 'value'] = random_values
print(df)


2 commentaires

Merci pour une réponse détaillée. J'ai une question concernant la partie size = len (random_rows) // 2 + 1 . si vous spécifiez le nombre de valeurs aléatoires avec size = len (random_rows) alors que fait // 2 + 1 ?


@Sascha len (random_rows) // 2 + 1 signifie (len (random_rows) // 2) + 1 . // correspond au étage ( ou entier) division donc nombre de lignes sélectionnées div 2 plus 1.



0
votes

Réponse similaire en utilisant un exemple :

Exemple df :

import pandas as pd 

df = pd.DataFrame({"time_col" : pd.date_range("2018-01-01", "2019-01-01", freq = "H")})
df["date"], df["time"] = df["time_col"].dt.date, df["time_col"].dt.hour 
df["value"] = pd.np.random.randint(100, 150, df.shape[0])

seed = 11 # deterministic behavior, that's what heroes do
rnd_rows_idx = df.sample(frac = 0.2, random_state=seed).index # grabbing indexes

original_rows = df.loc[rnd_rows_idx, "value"] # keeping a trace of original values

### Replacing the values selected at random ### 

df.loc[rnd_rows_idx, "value"] = pd.np.random.randint(1, 50, rnd_rows_idx.shape[0])


0 commentaires