Задача:
В фрейме данных столбцов product, day, pgroup, price (логический ключ = product, day) для некоторых строк столбец pgroup пуст. Если есть другие наборы данных для этого продукта, содержащие значение, их следует использовать для пустых наборов данных.

В настоящее время я просматриваю продукты, ищу уникальные значения группы для каждого продукта. Я бы хотел сделать это быстрее.

Пример:

Данные:

df = pd.DataFrame([['a','2018-02-03','G1',47],
              ['a','2018-02-04',None,25],
              ['a','2018-02-05','G1',10],
              ['a','2018-02-06',None,22],
              ['a','2018-02-07',None,84],
              ['b','2018-02-03',None,10],
              ['b','2018-02-04',None,21],
              ['b','2018-02-05',None,2],
              ['b','2018-02-06','G2',18],
              ['b','2018-02-07','G2',11],
              ['c','2018-02-03','G2',63],
              ['c','2018-02-04','G2',83],
              ['c','2018-02-05',None,20],
              ['c','2018-02-06',None,68],
              ['c','2018-02-07',None,33]])
df.columns = ['product','day','pgroup', 'value']

Код:

# Loop for each product
for xprod in df['product'].unique().tolist():
    # find unique values for pgroup
    unique_values = df[df['product'] == xprod]['pgroup'].unique()
    # Change Datatypes because of NaN-Values in Series
    unique_values_str = [str(i) for i in unique_values]
    # 2 values, first is NaN => take second 
    if len(unique_values_str) == 2 and (unique_values_str[0] == 'nan'):
        df.loc[df['product'] == xprod, 'pgroup'] = unique_values_str[1]
    # 2 values, second is NaN => take first
    elif len(unique_values_str) == 2 and (unique_values_str[1] == 'nan'):
        df.loc[df['product'] == xprod, 'pgroup'] = unique_values_str[0] 

Ожидаемый результат:

    product     day         pgroup  value
0   a           2018-02-03  G1      47
1   a           2018-02-04  G1      25
2   a           2018-02-05  G1      10
3   a           2018-02-06  G1      22
4   a           2018-02-07  G1      84
5   b           2018-02-03  G2      10
6   b           2018-02-04  G2      21
7   b           2018-02-05  G2      2
8   b           2018-02-06  G2      18
9   b           2018-02-07  G2      11
10  c           2018-02-03  G2      63
11  c           2018-02-04  G2      83
12  c           2018-02-05  G2      20
13  c           2018-02-06  G2      68
14  c           2018-02-07  G2      33

Аннотация:
Согласно моему исследованию, большую часть времени занимают первые две строки:

 # Loop for each product
    for xprod in df['product'].unique().tolist():
        # find unique values for pgroup
        unique_values = df[df['product'] == xprod]['pgroup'].unique()
1
FreezeFrame 15 Мар 2019 в 19:01

1 ответ

Лучший ответ

Это кажется немного взломанным, и я действительно не знаю, как это будет работать, но я думаю, что это должно быть немного быстрее.

df2 = df
df2['pgroup'] = df.groupby(['product'])['pgroup'].transform(lambda x : repr(set(x) - set([None]) ).replace("{'",'').replace("'}",'') )

Вам также может потребоваться изменить способ очистки строки, созданной из repr, если это вызывает какие-либо проблемы со значениями, которые может принимать pgroup.

1
Ryan 15 Мар 2019 в 23:35