Как поменять местами значения между двумя столбцами в зависимости от условий в Python

Я пытаюсь переключить значения между столбцами Range и Unit в приведенном ниже фрейме данных при условии, что если Unit содержит -, то замените Unit на Range и Range на Unit. Для этого я создаю столбец unit_backup, чтобы не потерять исходное значение Unit.

1. фрейм данных

sample_df = pd.DataFrame({'Range':['34-67',12,'gm','45-90'],
              'Unit':['ml','35-50','10-100','mg']})
sample_df
    Range       Unit
0   34-67         ml
1   12         35-50
2   gm        10-100
3   45-90         mg

2. Функция Ниже приведен код, который я пробовал, но получаю сообщение об ошибке:

def range_unit_correction_fn(df):

    # creating backup of Unit column
    df['unit_backup'] = df['Unit']
    
    # condition check
    if df['unit_backup'].str.contains("-"):
        
        # if condition is True then replace `Unit` value with `Range` and `Range` with `unit_backup`
        df['Unit'] = df['Range']
        df['Range'] = df['unit_backup']
        
    else:
        # if condition False then keep the same value
        df['Range'] = df['Range']
    
    # drop the backup column
    df = df.drop(['unit_backup'],axis=1)
    
    return df
  1. Применение вышеуказанной функции к кадру данных
sample_df = sample_df.apply(range_unit_correction_fn, axis=1)
sample_df

Ошибка:

   1061 def apply_standard(self):
   1062     if self.engine == "python":
-> 1063         results, res_index = self.apply_series_generator()
...
----> 4     if df['unit_backup'].str.contains("-"):
      5         df['Unit'] = df['Range']
      6         df['Range'] = df['unit_backup']

AttributeError: 'str' object has no attribute 'str'

Это кажется какой-то глупой ошибкой, но я не уверен, где я ошибаюсь.

Цените любую помощь здесь.

🤔 А знаете ли вы, что...
Python позволяет создавать сценарии для автоматизации задач и обработки данных.


3
52
2

Ответы:

Решено

Когда вы получаете доступ к df['unit_backup'], вы получаете скалярное строковое значение, а не серию pandas, поэтому вызов .str по нему вызывает ошибку.

Чтобы исправить это, вы можете проверить условие непосредственно на строковом значении построчно:

def range_unit_correction_fn(df):
    # creating backup of Unit column
    df['unit_backup'] = df['Unit']

    # condition check
    if '-' in df['unit_backup']:
        # if condition is True then replace `Unit` value with `Range` and `Range` with `unit_backup`
        df['Unit'] = df['Range']
        df['Range'] = df['unit_backup']

    # drop the backup column
    df = df.drop(['unit_backup'])

    return df

В качестве альтернативы, в одной строке, без необходимости временного столбца или «резервной копии» столбца:

sample_df[['Range', 'Unit']] = sample_df[['Unit', 'Range']].where(sample_df['Unit'].str.contains('-'), sample_df[['Range', 'Unit']].values)

что дает:

    Range Unit
0   34-67   ml
1   35-50   12
2  10-100   gm
3   45-90   mg