Заполните пропущенные значения в выбранных столбцах отфильтрованными значениями в другом столбце

#python #regex #pandas #null #fillna

#python #регулярное выражение #pandas #null #заполните

Вопрос:

У меня есть странный столбец с именем null в dataframe, который содержит некоторые пропущенные значения из других столбцов. Один столбец — это координаты широты с именем location , другой — целое число, представляющее целевую переменную с именем level . В некоторых, но не во всех случаях, когда location или level имеют пропущенные значения, значения, которые должны быть там, находятся в этом null столбце. Вот пример df:

 pd.DataFrame(
     {'null': {0: '43.70477575,-72.28844073', 1: '2', 2: '43.70637091,-72.28704334', 3: '4', 4: '3'},
     'location': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan},
     'level': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan}
     }
)
  

Мне нужно иметь возможность фильтровать null столбец в соответствии с тем, является ли значение целым числом или строкой, а затем на основе этого заполнить пропущенное значение в соответствующем столбце соответствующим значением. Я пытался использовать .apply() с функцией лямбда, а также .match() , .contains() и in внутри цикла for, но пока безуспешно.

Комментарии:

1. каков ваш ожидаемый результат

2. Мне нужно иметь возможность фильтровать столбец null в зависимости от того, является ли значение целым числом или строкой, а затем, основываясь на этом, заполните его для пропущенного значения в соответствующем столбце (строки в ‘location’ и целые числа в ‘level’).

3. Проверьте мой ответ, дайте мне знать, работает ли он ~

Ответ №1:

Самый простой, если не самый простой подход, это просто заполнить все пропущенные значения в df.location и df.level значениями в df.null , затем создать логический фильтр с регулярным выражением, чтобы возвращать неподходящие / неправильно назначенные значения в df.location и df.level в np.nan .

pd.fillna()

 df = pd.DataFrame(
     {'null': {0: '43.70477575,-72.28844073', 1: '2', 2: '43.70637091,-72.28704334', 3: '4', 4: '3'},
     'location': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan},
     'level': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan}
     }
)

for col in ['location', 'level']:
     df[col].fillna(
          value = stress.null,
          inplace = True
     )
  

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

str.contains()

 # Converting columns to type str so string methods work
df = df.astype(str)

# Using regex to change values that don't belong in column to NaN
regex = '[,]'
df.loc[df.level.str.contains(regex), 'level'] = np.nan
    
regex = '^d.?0?$'
df.loc[df.location.str.contains(regex), 'location'] = np.nan
    
# Returning `df.level` to float datatype (str is the correct
# datatype for `df.location`
df.level.astype(float)
  

Вот результат:

 pd.DataFrame(
     {'null': {0: '43.70477575,-72.28844073', 1: '2', 2: '43.70637091,-72.28704334', 3: '4', 4: '3'},
      'location': {0: '43.70477575,-72.28844073', 1: nan, 2: '43.70637091,-72.28704334', 3: nan, 4: nan},
      'level': {0: nan, 1: '2', 2: nan, 3: '4', 4: '3'}
     }
)
  

Ответ №2:

Давайте попробуем to_numeric

 checker = pd.to_numeric(df.null, errors='coerce')
checker
Out[171]: 
0    NaN
1    2.0
2    NaN
3    4.0
4    3.0
Name: null, dtype: float64
  

И примените, isnull если возврат NaN означает, что это строка, а не int

 isstring = checker.isnull()
Out[172]: 
0     True
1    False
2     True
3    False
4    False
Name: null, dtype: bool
# isnumber = checker.notnull()
  

Заполните значение

 df.loc[isnumber, 'location'] = df['null']
df.loc[isstring, 'level'] = df['null']
  

Комментарии:

1. Этот код может фильтровать столбец null для целых чисел, но он не заполняет пропущенные значения в столбце level этими значениями.

2. @KristianCanler вы можете заполнить вышеуказанное условие, также проверьте обновление

Ответ №3:

Другой подход может использовать метод pandas.Series.mask :

 >>> df
                       null  location  level
0  43.70477575,-72.28844073       NaN    NaN
1                         2       NaN    NaN
2  43.70637091,-72.28704334       NaN    NaN
3                         4       NaN    NaN
4                         3       NaN    NaN
>>> df.level.mask(df.null.str.isnumeric(), other = df.null, inplace = True)
>>> df.location.where(df.null.str.isnumeric(), other = df.null, inplace = True)
>>>
>>> df
                       null                  location level
0  43.70477575,-72.28844073  43.70477575,-72.28844073   NaN
1                         2                       NaN     2
2  43.70637091,-72.28704334  43.70637091,-72.28704334   NaN
3                         4                       NaN     4
4                         3                       NaN     3

  

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas .Series.mask.html
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas .Series.where.html

Комментарии:

1. Извините, мне нужно было обновить фрейм данных! Это была отредактированная версия. Теперь у меня есть правильное значение в OP.

2. Когда я реализую этот код, кажется, что он заполняет некоторые строки в df.level, которые должны быть целыми числами.