Удаление всех нечисловых значений массива

#python #arrays #python-3.x #string #pandas

#python #массивы #python-3.x #строка #pandas

Вопрос:

У меня есть массив, который я хочу очистить, в котором есть записи типа:

 arr = (['1140.0', '-600.0', '-700.6', '5700.45', '(~par)', '(-6.0', '690.6', ....., 
'-----', '5750.65', '#', '-850.0'])
  

Я хочу очистить этот массив от всех non-numeric значений и сохранить порядок в массиве, чтобы получить такой результат:

 arr_clean = (['1140.0', '-600.0', '-700.6', '5700.45', '690.6', '5750.65', '-850.0'])
  

Некоторые значения отрицательны, поэтому я не могу просто посмотреть, является ли первый символ элемента нечисловым, а в некоторых значениях есть цифры, но их также нужно удалить — например, значение (-6.0 .

Сначала я преобразовал в dataframe, чтобы посмотреть, смогу ли я просто изменить pd.to_numeric(df[col]) и очистить его таким образом, но мне кажется неэффективным переключаться туда-сюда с массива на df и обратно (размер массива составляет ~ 800 000, и я хочу, чтобы мой конечный результат был массивом).

Есть ли простой способ сделать это?

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

1. array вы имеете в виду список Python? Если да, то почему () ? Или это чепуха ndarray ? Если да, то какова форма и dtype?

Ответ №1:

Выполнение float('(-6.0') вызовет исключение, если оно не является числом. Использование этой функции идеально подходит для pythonic (утиный ввод):

 arr = (['1140.0', '-600.0', '-700.6', '5700.45', '(~par)', '(-6.0', '690.6', '...',
'-----', '5750.65', '#', '-850.0'])

arr_clean = list()

for elm in arr:
    try:
        float(elm)
        print("could     convert string to float:", elm)
        arr_clean.append(elm)
    except ValueError as e:
        print(e)

print(arr_clean)
  

Это выводит:

 could     convert string to float: 1140.0
could     convert string to float: -600.0
could     convert string to float: -700.6
could     convert string to float: 5700.45
could not convert string to float: '(~par)'
could not convert string to float: '(-6.0'
could     convert string to float: 690.6
could not convert string to float: '...'
could not convert string to float: '-----'
could     convert string to float: 5750.65
could not convert string to float: '#'
could     convert string to float: -850.0
['1140.0', '-600.0', '-700.6', '5700.45', '690.6', '5750.65', '-850.0']
  

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

1. Есть ли более эффективный способ, чем перебирать все элементы? Просто из-за размера моего фактического массива (около 800 000 элементов) это может потребовать слишком много вычислительной мощности.

2. Любая фильтрация займет не менее O(n) времени, если вы не распараллелите задачу или не переведете ее в код более низкого уровня. Честно говоря, я бы ожидал, что настройка распараллеливания займет больше времени, чем просто выполнение этого… Кроме того, я только что протестировал 800 000 с использованием строк 50/50 в сравнении с числами, и для запуска потребовалось 670 мс. Это слишком медленно для вашего варианта использования? Хм, когда вы его запускали, вы сохранили инструкции print? Убедитесь, что вы их удалили, если вы этого не сделаете, это займет намного больше времени. Используйте ключевое слово pass вместо print(e) в последней строке и просто удалите другое.

Ответ №2:

Если я могу предположить, что ваш массив array находится во фрейме данных, вы можете использовать pd.to_numeric with errors=coerce , а затем Dataframe.dropna :

 # Example dataframe which was provided
data = {'Array':['1140.0', '-600.0', '-700.6', '5700.45', '(~par)', '(-6.0', '690.6', '.....', '-----', '5750.65', '#', '-850.0']}

df = pd.DataFrame(data)
print(df)
      Array
0    1140.0
1    -600.0
2    -700.6
3   5700.45
4    (~par)
5     (-6.0
6     690.6
7     .....
8     -----
9   5750.65
10        #
11   -850.0
  

Применить pd.to_numeric

 pd.to_numeric(df.Array, errors='coerce').dropna()

0     1140.00
1     -600.00
2     -700.60
3     5700.45
6      690.60
9     5750.65
11    -850.00
Name: Array, dtype: float64
  

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

1. Я только что сравнил это с моим решением, и это занимает 445 мс, на 33% быстрее, чем мои 670 мс, (но с более длительной настройкой).