Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.09.2011, 13:54   #1
Dexter_M
Пользователь
 
Регистрация: 13.09.2011
Сообщений: 29
По умолчанию большой массив данных с несколькими переменными

Добрый день!

Возник такой вопрос:
есть .txt файл следующего вида:
index;yyyy;mm;dd;Tmin;Q;Tmid;Q;Tmax ;Q;R;CR;QR
часть файла во вложении (там несколько лет и один индекс)

Мне необходимо узнать средние суточные значения Tmid за последние xx лет по каждому индексу, т.е. "среднее Tmid первого января за последние 30 лет индексом таким-то составляла столько-то, второго января столько-то и т.д."
и необходимо подсчитать, как часто встречалась каждое значение Tmid за последние хх лет по каждому индексу.

никак не могу придумать, как это реализовать.
знакомый посоветовал создать массив Tmid(yy,mm,dd), но, сделав его я так и не понял, как мне с ним дальше плясать.
Пытался сделать перечислением переменных по очереди, но получается уж очень долго.
Может кто-чего посоветует???

P.S.: С VBA работаю совсем недавно...
стоит MS Office 2007
Вложения
Тип файла: rar SCH7FF11.rar (18.0 Кб, 16 просмотров)
Dexter_M вне форума Ответить с цитированием
Старый 22.09.2011, 14:09   #2
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

Массив создали?
Теперь прогоняете его через словарь - как отбор уникальных делаете по mm & "|" & dd, результаты складываете в другой параллельный массив.
Туда помещаете количество повторов и сумму - потом (или сразу) можно подбить среднее.
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Старый 22.09.2011, 14:35   #3
Dexter_M
Пользователь
 
Регистрация: 13.09.2011
Сообщений: 29
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
Массив создали?
Теперь прогоняете его через словарь - как отбор уникальных делаете по mm & "|" & dd, результаты складываете в другой параллельный массив.
Туда помещаете количество повторов и сумму - потом (или сразу) можно подбить среднее.
а не подскажите, как это делается?
Dexter_M вне форума Ответить с цитированием
Старый 22.09.2011, 14:47   #4
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

Вот отбор уникальных (и суммирование сумм) из массива, который получен с листа:
Код:
http://www.planetaexcel.ru/forum.php?thread_id=26105

Option Explicit

Sub UniqSummUniversal() 'вариант без Transpose - для больших объёмов
'Выделить диапазон, где в первом столбце - неуникальные, в последнем - суммы
Dim a(), b(), oDict As Object, i&, ii&, temp$, x&
Dim ind&
'Dim tm: tm = Timer
a = Selection.Value
ReDim b(1 To UBound(a, 1), 1 To 2)
ind = UBound(a, 2)
Set oDict = CreateObject("Scripting.Dictionary")
oDict.CompareMode = 1
For i = 1 To UBound(a)
    If Not IsEmpty(a(i, ind)) Then
        If IsNumeric(a(i, ind)) Then
        temp = Trim(a(i, 1))
            If Not oDict.Exists(temp) Then
            ii = ii + 1
            b(ii, 1) = temp: b(ii, 2) = a(i, ind)
            oDict.Add temp, CStr(ii)
            Else
            x = oDict.Item(temp)
            b(x, 2) = b(x, 2) + a(i, ind)
            End If
        End If
    End If
Next

On Error Resume Next 'если вдруг ii=0
With Workbooks.Add.Worksheets(1)
.Columns(1).NumberFormat = "@"
.Range("A1:B1").Resize(ii) = b
End With
On Error GoTo 0
'Debug.Print Timer - tm
End Sub
Сюда добавить ещё подсчёт количества повторов и среднее.
В общем, на этой основе можно сделать - что-то добавить, что-то выкинуть.
Вместо temp = Trim(a(i, 1)) даёте свою склейку дата+месяц.
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Старый 22.09.2011, 21:48   #5
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

Попробуйте.
Массив создал сам, одной строкой.
В файле-результате столбцы Tsum и Tcount может быть и не нужны, но для информации не лишние.
Путь к текстовику поставьте свой.
Почти без изменений взял приведённый выше код.

Код:
Sub tt()

    Dim a, b(), oDict As Object, i&, ii&, temp$, x&, sep_$

    a = Split(CreateObject("Scripting.FileSystemObject").OpenTextFile("c:\Temp\Dexter_M\SCH7FF11.txt", 1).ReadAll, vbNewLine)
    sep_ = Mid$(1 / 2, 2, 1)

    'Dim tm: tm = Timer
    ReDim b(1 To UBound(a, 1), 1 To 6)
    Set oDict = CreateObject("Scripting.Dictionary")
    oDict.CompareMode = 1
    For i = 0 To UBound(a)
        If Len(Trim(a(i))) Then
            aa = Split(Replace(a(i), ".", sep_), ";")
            If Len(Trim(aa(7))) Then
                temp = aa(0) & "|" & aa(2) & "|" & aa(3)
                If Not oDict.Exists(temp) Then
                    ii = ii + 1
                    b(ii, 1) = aa(0): b(ii, 2) = aa(2): b(ii, 3) = aa(3)
                    b(ii, 4) = --aa(7): b(ii, 5) = 1: b(ii, 6) = --aa(7)
                    oDict.Add temp, CStr(ii)
                Else
                    x = oDict.Item(temp)
                    b(x, 4) = b(x, 4) + aa(7): b(x, 5) = b(x, 5) + 1: b(x, 6) = b(x, 4) / b(x, 5)
                End If
            End If
        End If
    Next

    On Error Resume Next    'если вдруг ii=0
    With Workbooks.Add.Worksheets(1)
        .Range("A1:F1") = Split("index mm dd Tsum Tcount Tmid")
        .Columns(1).NumberFormat = "@"
        .Range("A2:F2").Resize(ii) = b
    End With
    On Error GoTo 0
    'Debug.Print Timer - tm

End Sub
Хотя вероятно можно и на SQL сделать, но я больше массивы использую - кажется, что так контроля больше. И кажется быстрее - интересно было бы сравнить на этой задаче два подхода по скорости.
Вот только что-то на ADO вариантов не предлагают...

P.S.
Цитата:
за последние xx лет
- можно и это в код добавить - отбирать данные только за года, попадающие в выборку.
Добавить всего одну проверку aa(1).

P.P.S. А почему по вопросу с csv не отписались? Я волнуюсь... Ещё одна тема без результата - и всё...
И кстати, тот код и этот - буквально братья, не находите? В принципе, если бы в том разобрались - этот вопрос могли бы и не задавать...
И этот вообще, и
Цитата:
а не подскажите, как это делается?
в частности...

И ещё - в описании явно ошибка, не вяжется
Цитата:
index;yyyy;mm;dd;Tmin;Q;Tmid;Q;Tmax ;Q;R;CR;QR
27612;1949; 1;26;0; -6.8;0; -3.1;0; -0.7;0; 0.0;2;0
Я брал данные так, как мне казалось правильным.
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 22.09.2011 в 22:36.
Hugo121 вне форума Ответить с цитированием
Старый 23.09.2011, 09:03   #6
Dexter_M
Пользователь
 
Регистрация: 13.09.2011
Сообщений: 29
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
Попробуйте.
Массив создал сам, одной строкой.
В файле-результате столбцы Tsum и Tcount может быть и не нужны, но для информации не лишние.
Путь к текстовику поставьте свой.
Почти без изменений взял приведённый выше код.
Спасибо, сейчас же попробую!

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
P.P.S. А почему по вопросу с csv не отписались? Я волнуюсь... Ещё одна тема без результата - и всё...
Тот код работает прекрасно!, именно так как надо! проверил несколько значений, выборочно, все посчитано правильно.
Мне казалось, что я отписывался, щас исправлюсь.

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
И кстати, тот код и этот - буквально братья, не находите? В принципе, если бы в том разобрались - этот вопрос могли бы и не задавать...
Честно, изначально пытался сделать по тому коду... я сейчас сижу с тремя учебниками по VBA. пытаюсь во всем разобрать и научиться самому, т.к. неудобно по каждой проблеме сюда обращаться... но результат пока скромный...

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
И ещё - в описании явно ошибка, не вяжется
Да, Вы правы. пропустил:
index;yyyy;mm;dd;Q;Tmin;Q;Tmid;Q;Tmax ;Q;R;CR;QR
27612;1949; 1;26;0; -6.8;0; -3.1;0; -0.7;0; 0.0;2;0
Dexter_M вне форума Ответить с цитированием
Старый 23.09.2011, 09:25   #7
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

Ну и отлично.
В коде ничего сложного нет -
1. Читаем весь текст в массив, разбивая по строкам.
Тут вероятно может быть сложность, если файл будет уж очень большой, на сотни мегабайт. Но я с такими так не работал, поэтому точно не знаю.
Иногда приходится разбивать не по vbNewline, а по chr(13) - зависит от конкретного файла.
В общем - тут главное любым способом получить массив строк.
Или можно вместо массива читать построчно непосредственно файл, хотя это вероятно будет медленнее, но как вариант при работе с огромным файлом (который трудно сразу весь запихннуть в память) вполне возможен.
2. Перебираем этот массив, разбивая теперь уже каждую строку по ";".
Кстати, забыл Dim aa сделать... Не критично, но может ругнуться, если Option Explicit стоит.
Но я сперва на ходу заменяю точки на системный разделитель - у меня с точками не работает. Хотя Вам возможно заменять точку на точку и лишнее
3. Отбираем в словарь значение, собранное из индекса, даты и месяца.
В параллельный массив для этого значения помещаем нужные данные.
4. При повторе изменяем по этому уникальному его значения в массиве.
5. Выгружаем результат. Выгружать можно как угодно - в новую книгу или в новый лист, или на этот же лист, или даже писать в другой текстовый файл - не принципиально.

Есть ещё мелочи по откидыванию ненужных пустых строк (If Len(Trim(a(i))) Then) и строк без значимых значений (If Len(Trim(aa(7))) Then), но это уже несущественные, хотя и необходимые мелочи. Но это можно было бы сделать и иначе.

P.S. Забыл про "и необходимо подсчитать, как часто встречалась каждое значение Tmid за последние хх лет по каждому индексу."
Это можно тоже сразу сделать, но нужно создать второй словарь и второй массив для результатов, параллельно двум уже существующим. Пока подробно не продумывал, но вероятно алгоритм похож - как уникальные собираем связку индекс & "|" & среднее, считаем повторы.
Попробуйте сами сделать - можно сперва в отдельном коде только на эту задачу, а потом совместить (если нужно сразу обе задачи выполнять)
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 23.09.2011 в 10:37. Причина: Забыл про "и необходимо...
Hugo121 вне форума Ответить с цитированием
Старый 23.09.2011, 10:43   #8
Dexter_M
Пользователь
 
Регистрация: 13.09.2011
Сообщений: 29
По умолчанию

Спасибо!!!
щас сижу и пытаюсь сам сделать это. Ваше пояснение к коду помогло, т.к. не мог понять основное тело кода (никогда не сталкивался со словарем). теперь стало гораздо яснее.
Как чего сделаю - отпишусь.
Dexter_M вне форума Ответить с цитированием
Старый 23.09.2011, 11:49   #9
R Dmitry
Форумчанин
 
Регистрация: 07.03.2010
Сообщений: 796
По умолчанию

Игорь на ADO есть не только Варианты, но и готовое "многоотчетное" решение, предложение отправил в личку
Логика?!.... она где то рядом... E_mail: dg_rusak@mail.ru Если спасибо мало: Яндекс . Деньги - 41001731366021 WM R269866874234
R Dmitry вне форума Ответить с цитированием
Старый 23.09.2011, 11:52   #10
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

Я только ЗА - больше решений, хороших и разных!
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Дан динамический массив строк, вывести все слова начинающиеся с большой буквы C++ builder Memphi[s] Помощь студентам 0 02.03.2011 16:34
Большой объем данных matanga Microsoft Office Excel 4 09.12.2010 13:14
SQL - обьединение и управление несколькими базами данных MarinN SQL, базы данных 1 08.11.2010 10:09
Как виделить большой кусок памяти под массив? Tania Мультимедиа в Delphi 7 23.04.2010 01:53
Поиск min/max данных с несколькими условиями - нужна помощь! /nort/ Microsoft Office Excel 3 16.03.2008 00:13