Перебирайте строки и присваивайте значение на основе условия - PullRequest
0 голосов
/ 31 мая 2019

У меня есть даты для каждой строки в моем фрейме данных, и я хочу присвоить значение новому столбцу на основе условия даты.

Обычно, если я назначаю значение новому столбцу, я бы сделалчто-то вроде этого:

def get_mean(df):
   return df.assign(
     grouped_mean = lambda df: df.groupby('group')['X']
       .transform(lambda df: df.mean())
   )

Нет, я ищу подобное решение, так как решение, которое у меня сейчас есть, очень медленное и не красивое.

Есть ли лучший способ, чем мой нынешнийрешение и использование assign?

В настоящее время я придумала это решение:

def set_season(df):
    df = df.copy()
    for i in df.index:
        if (df.loc[i, 'Date'] >= pd.Timestamp('2008-08-30')) & (df.loc[i, 'Date'] <= pd.Timestamp('2009-05-31')):
            df.at[i, 'season'] = '08-09'
        elif  (df.loc[i, 'Date'] >= pd.Timestamp('2009-08-22')) & (df.loc[i, 'Date'] <= pd.Timestamp('2010-05-16')):
            df.at[i, 'season'] = '09-10'
        elif  (df.loc[i, 'Date'] >= pd.Timestamp('2010-08-28')) & (df.loc[i, 'Date'] <= pd.Timestamp('2011-05-22')):
            df.at[i, 'season'] = '10-11'

    return df

Ответы [ 2 ]

3 голосов
/ 31 мая 2019

В пандах и в большинстве случаев в Python вообще мы хотим избежать зацикливания наших данных , потому что это может быть медленнее, до коэффициентов 1000x. Pandas и numpy предоставляют множество векторизованных решений для большинства наших проблемных случаев. Подробнее об этом здесь

В вашем случае мы можем использовать np.select, что позволяет нам определять несколько условий и на основе этих условий мы определяем варианты выбора .

Кроме того, мы можем сделать ваш код более элегантным, используя Series.between с аргументом inclusive=True.

conditions = [
    df['Date'].between('2008-08-30', '2009-05-31', inclusive=True),
    df['Date'].between('2009-08-22', '2010-05-16', inclusive=True),
    df['Date'].between('2010-08-28', '2011-05-22', inclusive=True)
]

choices = ['08-09', '09-10', '10-11']

df['season'] = np.select(conditions, choices, default='99-99')

Sidenote

Мы также можем переписать вашу первую функцию лучше, удалив две функции lambda и просто назначив новый столбец с groupby и transform, а также приняв дополнительные аргументы: group & mean_col

def get_mean(df, group, mean_col):

    df['mean'] = df.groupby(group)[mean_col].transform('mean')

    return df

Пример * ** 1 038 тысяча тридцать семь * # Example dataframe df = pd.DataFrame({'Fruit':['Banana', 'Strawberry', 'Apple', 'Banana', 'Apple'], 'Weight':[10, 12, 8, 9, 14]}) Fruit Weight 0 Banana 10 1 Strawberry 12 2 Apple 8 3 Banana 9 4 Apple 14 get_mean(df, 'Fruit', 'Weight') Fruit Weight mean 0 Banana 10 9.5 1 Strawberry 12 12.0 2 Apple 8 11.0 3 Banana 9 9.5 4 Apple 14 11.0

0 голосов
/ 31 мая 2019

Используйте метод .apply(), если новый столбец 'season' зависит только от одного столбца:

def your_function(date):
    """
    takes a date a returns a string season
    """
    # code your function here

df['season'] = df['Date'].apply(your_function)

, если ваш новый столбец 'season' зависит от нескольких других столбцов, используйте axis = 1:

def your_function(row):
    """
    takes a row from your dataframe and returns a result
    """
    # code your function here
    # example if you want a sum of col1, col2, col3
    return row['col1'] + row['col2'] + row['col3']

df['season'] = df.apply(your_function, axis = 1)
...