Страницы: Пред. 1 2 3 След.
RSS
Фильтрация по 2000 условий
 
New, спасибо
Значит bedvit всё понял и описал в точности по вашей задаче. Безусловно, это отличная демонстрация Фильтра.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
На Питоне сама фильтрация тоже заняла 15 секунд, остальное время потрачено на обращение к к файлам (чтение/запись).
Итого у меня получилось 34 сек. ))
Комп довольно старый, плюс куча запущенных программ.

Код
2022-09-14 16:04:46.665 | INFO     | __main__:<module>:6 - Чтение из файла списка фраз
2022-09-14 16:04:55.125 | INFO     | __main__:<module>:9 - Чтение из файла стоп-слов
2022-09-14 16:04:55.218 | INFO     | __main__:<module>:12 - Фильтрация списка фраз по отсутствию стоп-слов
2022-09-14 16:05:10.418 | INFO     | __main__:<module>:15 - Сохранение результата в файл
2022-09-14 16:05:20.215 | INFO     | __main__:<module>:22 - Финиш
Изменено: nilske - 14.09.2022 16:17:06
 
Зачиньщики, уточните все ж что значит слово входит
"Азов"  входит в "газовая плита" или нет? "Петебург" и "санкт-петербург"?

Цитата
nilske написал:
Итого у меня получилось 34 сек. ))
у меня сперва тоже 5 секунд заняло, потом  только оказалось что результат неверен.
Изменено: БМВ - 14.09.2022 16:29:55
По вопросам из тем форума, личку не читаю.
 
Мое решение учитывает и "азов" и "Петербург". Потому как в примере от Павла в этом списки и куски слов и часть фразы. Т.е. любой кусок символов в исходных данных проверяется, и если находится, эта строка исключается из списка.
«Бритва Оккама» или «Принцип Калашникова»?
 
nilske, для Пайтона (Питона) неплохо, какие библиотеки использовали?
Какой размер списка итогового?
Какой пример использовали, из какого сообщения?
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, Pandas, список от автора (без дополнительных столбцов)
по итогу получилось 273331 записей

P.S. Блин, наверное неправильно - ведь у нас стоп-слова, а не стоп-строки )))
Переделаю как будет время.
Изменено: nilske - 14.09.2022 17:22:24
 
nilske, да, там вся соль в том,  что нужно искать ВХОЖДЕНИЯ  из списка слов (часть слова, кусок строки) в строку главного списка, а не равенство.
В питоне это помоему find для строки или in
Изменено: bedvit - 14.09.2022 17:43:09
«Бритва Оккама» или «Принцип Калашникова»?
 
Как любитель встроенных инструментов провел тест с расширенным фильтром
1. стандартный, для этого пришлось правда развернуть таблицу с критериями, так как нужно условие AND

Данные Данные         Данные
<>*спб* <>*бесплатно* <>*бумаг*
....
Результат почти в 2 раза хуже чем в следующем варианте (789,1132813 по таймеру)
2. С использованием формулы для критеия так как  массивные там нужно использовать или через симуляцию или через имена, то избрана быстрая
=COUNT(INDEX(FIND(LOWER('Стоп-слова'!A$2:A$2098);LOWER(A2));))=0
и результат по таймеру 296,8828125
Код
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
t = Timer
    Range("Таблица1[[#All],[Данные]]").AdvancedFilter Action:=xlFilterCopy, _
        CriteriaRange:=Range("d1:d2"), CopyToRange:=Range("K1"), Unique _
        :=False
    DoEvents
Debug.Print Timer - t
Range("f1") = Timer - t
t = Timer
'    Range("Таблица1[[#All],[Данные]]").AdvancedFilter Action:=xlFilterCopy, _
'        CriteriaRange:=Worksheets("Стоп-слова").Range("d1:d2098"), CopyToRange:=Range("L1"), Unique _
'        :=False
    Range("Таблица1[[#All],[Данные]]").AdvancedFilter Action:=xlFilterCopy, _
        CriteriaRange:=Worksheets("Стоп-слова").Range("F1:CBV2"), CopyToRange:=Range("M1"), Unique _
        :=False
    DoEvents
Debug.Print Timer - t
Range("G1") = Timer - t
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True


предварительной подготовкой критериев и удаления её после думаю можно пренебречь.
выведено в обоих вариантах 229892 значений, произвел обратную проверку, стоп слов в результате не выявлено.
По вопросам из тем форума, личку не читаю.
 
после быстрой переделки на Python получилось 211354 значений и почти 4 минуты, ничего не проверял и почти без Pandas - абы как, лишь бы работало :)
завтра буду оптимизировать
 
БМВ, nilske, что-то у вас разное количество. Где правда?)
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
Где правда?)
я змеям не верю :-) Кроме зеленого :-). Я брал файл от New. У меня совпал результат двумя разными методами + проверял формулу прямо в таблице.
По вопросам из тем форума, личку не читаю.
 
Можно сравнить два списка-результата и проверить "излишек" ;)
 
Цитата
New написал:
Файл 5мб со всеми фразами и стоп-словами выложил сюда  https://disk.yandex.ru/d/xBcLbAOmODyIIg
Тестовое задание берем из сообщения 24?
«Бритва Оккама» или «Принцип Калашникова»?
 
По данным из 24 поста. Без заголовков. Итоговая таблица по параметрам: не содержит подстроку, с учетом регистра - 242343 итоговых строки. Без учета регистра - 229892 (совпадает с Михаилом)
Время расчета: с учетом регистра - 17сек
без учета регистра-600 сек=10 мин.
Здесь не оптимален алгоритм, строки преобразуются в один регистр при сравнении. Когда условие 1 , все ок. Когда условий 2000 - каждый раз при новом условии, при поиске подстроки происходит преобразование в один регистр. Итого исходная таблица преобразуется 2000 раз в один регистр. Нужно выносить разрвое преобразование таблиц в один регистр, и уже сравнивать данные в одном регистре. Ускорения в 2000 раз не будет, но выйдем на секунды, а не минуты.
Есть соображение распарралелить алгоритм в фильтре.
Будет время, выложу здесь результаты и релиз.
Изменено: bedvit - 15.09.2022 09:46:57
«Бритва Оккама» или «Принцип Калашникова»?
 
Всем - доброе утро!
Вариант на чистом VBA.
На моем компьютере в режиме ISDEBUG=0 (с удалением строк) общее время 8.5 секунд.
Регистр не важен.
При ISDEBUG=1 (без удаления строк, отображаются номера строк стопов) общее время 8.3 секунды.
Данных: 273495 (из сообщения #24)
Стопов: 43603 (найдено в данных)
Разность: 229892

Код
Option Explicit

Sub DelRowsByStops()
'ZVI:2022-09-15 https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&TID=152076#message1215688
'(post #45)
  
  Const ISDEBUG As Boolean = 1 ' 0/1 or False/True
  
  Dim a(), b()
  Dim i&, j&, k&
  Dim sWhere As String, sWhat As String, sDelim1 As String, sDelim2 As String, sDelim3 As String
  Dim rWhere As Range
  Dim bIsNum As Boolean
  Dim t As Single
  
  t = Timer
  
  If Not ISDEBUG Then
    Application.ScreenUpdating = False
    On Error GoTo exit_
  End If
  
  Debug.Print "ISDEBUG = " & IIf(ISDEBUG, 1, 0)
  
  If Лист1.FilterMode Then Лист1.ShowAllData
  Лист1.ListObjects(1).AutoFilter.ShowAllData
    
  sDelim1 = Chr(1)
  sDelim2 = Chr(2)
  sDelim3 = Chr(3)
  
  Set rWhere = Лист1.Range("A1").CurrentRegion.Columns(1)
  a() = rWhere.Value2
  ReDim b(2 To UBound(a))
  For i = 2 To UBound(a)
    b(i) = sDelim1 & i & sDelim2 & LCase(a(i, 1))
  Next
  sWhere = Join(b, sDelim3)
  ReDim b(1 To UBound(a), 1 To 1)
  If ISDEBUG Then
    b(1, 1) = "Стоп_№"
  End If
    
  a() = Лист2.Range("A1").CurrentRegion.Value2
  For i = 2 To UBound(a)
    sWhat = LCase$(a(i, 1))
    bIsNum = CStr(Val(sWhat)) = sWhat
    j = 1
    Do
      j = InStr(j, sWhere, sWhat)
      If j > 0 Then
        k = InStrRev(sWhere, sDelim1, j)
        If bIsNum Then
          If InStrRev(sWhere, sDelim2, j) > k Then
            k = Val(Mid$(sWhere, k + 1, 10))
            If ISDEBUG Then b(k, 1) = i Else b(k, 1) = 1
          End If
        Else
          k = Val(Mid$(sWhere, k + 1, 10))
          If ISDEBUG Then b(k, 1) = i Else b(k, 1) = 1
        End If
        j = j + Len(sWhat)
      Else
        Exit Do
      End If
    Loop
  Next
  
  Debug.Print "Main", Round(Timer - t, 3)
  rWhere.Columns(2).Value = b()
  
  If Not ISDEBUG Then
    With rWhere.Resize(, 2)
      .Sort Key1:=.Cells(1, 2), Order1:=xlAscending, Header:=xlYes
      i = WorksheetFunction.Count(.Columns(2))
      If i > 0 Then
        .Cells(2, 2).Resize(i).EntireRow.Delete
        .Columns(2).Clear
      End If
      .Cells(1, 2).Value = "Удалено: " & i
    End With
  End If
  With rWhere
    .Columns(2).EntireColumn.AutoFit
    .ListObject.Resize rWhere.Columns(1)
  End With
  
exit_:
  
  Application.ScreenUpdating = True
  Debug.Print "All", Round(Timer - t, 3)
  
End Sub

Если ListObjects не используются (обычные данные), то  закомментировать пару строк, где есть ListObject(s)
Изменено: ZVI - 15.09.2022 10:40:12
 
Доброе утро! Владимир, рад, что вы присоединились к обсуждению по теме. Решение хорошо оптимизированно под задачу и выдает отличные результаты. У меня отработало так (ПК рабочий, вполне неплохой) main - 7.99 сек., ALL - 8.59
«Бритва Оккама» или «Принцип Калашникова»?
 
У меня был другой файл - с расширением xlsm, кнопкой "Старт", с другим количеством строк и без умных таблиц.

Результаты с этим файлом тем же способом -
Количество записей в результате - 229892
Скорость в сравнении  - ... как у черепахи змеи.
 
Цитата
bedvit написал: Доброе утро
Доброе утро, Виталий!
Мне Ваш вариант с фильтром тоже понравился: эффективно, внешне просто, универсально.
С тормозами в C/C++ при преобразовании регистра сталкивался, правда, с посимвольным. Возможно, преобразование всей строки там быстрее, но нужно угадать еще и кодовую страницу. Проще LCase сделать в VBA.
 
nilske, попробуйте оптимизировать алгоритм, применить прралельные расчеты, к примеру разделите список на 4/8/16 (по количеству логических процессоров) и обрабатывайте части в каждом потоке отдельно. Потом результат склеить и вывести.
ZVI, Владимир, да проблемы с угадыванием кодовой страницы есть, и преобразование в нижний или верхний регистр посимвольно. Для целой строки не нашел штатного инструмента. Вообщем, еще та задача. А как угадывает кодовую страницу LCase в VBA?
Изменено: bedvit - 15.09.2022 12:15:15
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал: А как угадывает кодовую страницу LCase в VBA?
Быстро 🙂
Что внутри - MS его знает...
Но Excel изначально эффективно ориентирован на поддержку мультиязычности и это видно по тестам
 
Добрый день, коллеги!
Большое спасибо за интересные и содержательные сообщения!

Цитата
bedvit написал:
А как угадывает кодовую страницу LCase в VBA?
VBA работает со строками в юникоде. Преобразование регистра забито непосредственно в таблицах юникода.
Изменено: sokol92 - 15.09.2022 12:39:36
Владимир
 
""
Изменено: testuser - 16.09.2022 02:03:10
 
Цитата
testuser написал:
Подумал, неплохо бы их подсветить )
А прежде надо было подумать, каким боком это к этой теме относится.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
А прежде надо было подумать, каким боком это к этой теме относится.
Просто для сопоставления. Получается, что время работы макроса от ZVI сопостовимо со временем работы функции SpecialCells с полученными данными в этом же диапазоне.
 
Цитата
testuser написал:
Получается, что время работы макроса от ZVI сопостовимо со временем работы функции SpecialCells с полученными данными в этом же диапазоне.
Я могу привести кучу примеров время выполнения в которых будет сопоставимо и что?
А вот тоже но с временем несопоставимым
Код
        Range(Cells(1), Cells(1).End(xlDown)).Offset(, 1).AutoFilter Field:=1, Criteria1:="<>", _
        Operator:=xlAnd
    Range(Cells(1).Offset(1), Cells(1).End(xlDown)).Interior.Color = 65535
    ActiveSheet.ShowAllData


Я спрашивал как оно к теме относится?  Зачем это сравнение?
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
А вот тоже но с временем несопоставимым
Да пожалуй ) Не стоило приводить тот пример, тем более, что он слишком медленный
Изменено: testuser - 16.09.2022 02:37:12
 
Распарралеливание алгоритма дает пока всего 30% прироста. Задача хорошо парралелится, но к  сожалению узкое горлышко не процессорное время, а работа с памятью. А она одна, в отличии от процессоров. Есть ли толк дальше оптимизировать парралельный алгоритм пока под вопросом.
Далее, отличные результаты Владимира на VBA меня порадовали, я вчера думал, почему у меня медленее отрабатывает и прешел к выводу, что нужно платить за универсальность ( т.к. это универсальный фильтр массива, а не узкоспециализировнное решение данной задачи) и на самом деле операции делаю в разы больше из-за этого. У мяня проверяются входящие параметры от пользователя на корректность заполнения, это 6 переменных для одного параметра * 2000 = уже проверка 12 тыс записей, еще даже не начиная основной алгоритм. Потом проверка приоритетов AND, перед OR. Проставляем, если пользователь сам скобками не отметил. Потом создание стеков, под каждые открывающие скобки отдельный стек (если есть скобки, в этой задаче нет скобок в условии, все в базовом стеке считается). Это все в однопоточном режиме. При закрытие скобок, стек закрывается, результат обрабатывается на уровне ниже, и так пока внутри всех скобок не будет рассчитаны итоги. Последний уровень нулевой (без скобок). Этот блок расчетов распарралелен.
Далее по итоговому стеку/массиву индексов или перекладываем массив на вывод индексов либо формируем по ним итоговый массив (2 режима вывода результата). Это тоже в 1 потоке.
Итого это 15 сек (10 если парралель.).
Еще проблемы с регистром (буду думать над быстрым вариантом преобразования)
И возможно VBA здесь сможет удержать лидерство.
Изменено: bedvit - 16.09.2022 08:53:53
«Бритва Оккама» или «Принцип Калашникова»?
 
При работе некоторых макросов складывается ощущение, что Эксель распределяет нагрузку по ядрам. Можно ли назвать это распараллеливанием?
Изменено: testuser - 16.09.2022 14:12:32 (многопоточный макрос или чО?)
 
ZVI, спасибо
 
Цитата
New написал: ZVI , спасибо
Рад, что как-то сработало!  :D
Страницы: Пред. 1 2 3 След.
Наверх