#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 мс, (но с более длительной настройкой).