Заполните пропущенные значения в таблице - PullRequest
3 голосов
/ 02 февраля 2011

У меня есть список дат и цен:

Date           Price
1/3/2000        10.00
1/5/2000        10.45
1/7/2000        10.25
...               ...

У меня есть отдельный список дат со всеми датами:

Date
1/1/2000
1/2/2000
1/3/2000
...

Мне нужно объединить их так, чтобыпредыдущая цена указана для дат, в которых отсутствуют цены:

Date            Price
1/1/2000         10.00
1/2/2000         10.00
1/3/2000         10.00
1/4/2000         10.00
1/5/2000         10.45
1/6/2000         10.45
1/7/2000         10.25
...               ...

В настоящее время я пытаюсь перебрать списки массивов, содержащие данные, но не могу правильно выстроить даты, особенно в начале и в конце,Я использую Java / Mysql / JDBC прямо сейчас, но я также открыт для R.Спасибо за любые предложения.

Ответы [ 5 ]

1 голос
/ 03 февраля 2011

Спасибо всем за помощь. Вот что я в итоге сделал: -Я создал список всех индексов, где совпадают даты.
-Я затем вставил цены в массив с тем же количеством элементов, что и полный список времени. - Затем я создал 3 цикла: один для элементов до первого соответствующего совпадения, один для элементов после последнего соответствующего элемента и, наконец, один для всего, что находится между ними.
-Эти три заполнили цены, которые отсутствовали.

Просто я бы поделился. Спасибо за вашу помощь.

public static void checkLengths(ArrayList<String> masterTimes, ArrayList<String> testTimes, ArrayList<Double> prices){
    ArrayList<Double> temp = new ArrayList<Double>();
    ArrayList<Integer> matches = new ArrayList<Integer>();
    Double[] temp2 = new Double [masterTimes.size()];
    int mt = masterTimes.size();
    int tt = testTimes.size();
        if(mt == tt){
            return;
        }else{
            int mast = 0;
            int test = 0;
            String mt1 = masterTimes.get(0);
            String tt1 = testTimes.get(0);

            test = 0;
            for(int i = 0; i < masterTimes.size(); i++){
                mt1 = masterTimes.get(i);
                tt1 = testTimes.get(test);
                System.out.println(" | mt1: " + mt1 + " | tt1: " + tt1);
                    if(mt1.equals(tt1)){
                        matches.add(i);
                        System.out.println("Inserting: " + i);
                        if(test < testTimes.size()){
                        test++;
                        }
                        if(test == testTimes.size()){
                            break;
                        }
                    }
            }
            System.out.println("Matches:");
            printAL(matches);

            // puts in known prices.
            for(int i = 0; i < matches.size(); i++){
                int g = matches.get(i);
                temp2[g] =  prices.get(i);
            }

            System.out.println("FirstPrices:");
            printAR(temp2);

            // Finds index of first and last matching times.
            int matcher1 = matches.get(0);
            int ind = matches.size() - 1;
            int matcher2 = matches.get(ind);
            System.out.println("Matcher1:" + matcher1 + " | Matcher2: " + matcher2);

            // If a price is empty/null, it puts the prior price in it.
            for(int i = matcher1; i < matcher2; i ++){
                System.out.println(i + " | " + temp2[i]);
                if(temp2[i] == null){
                    System.out.println(temp2[i] + " | " + temp2[i-1]);
                    temp2[i] = temp2[i-1];
                }
            }
            System.out.println("SecondPrices:");
            printAR(temp2);

            // Deals with start.
            for(int i = matcher1; i >= 0; i--){
                if(temp2[i] == null){
                    temp2[i] = temp2[i+1];
                }
            }

            System.out.println("ThirdPrices:");
            printAR(temp2);

            // Deals with end.
            for(int i = matcher2; i < temp2.length; i++){
                if(temp2[i] == null){
                    temp2[i] = temp2[i-1];
                }
            }
            System.out.println("FourthPrices:");
            printAR(temp2);             

            prices.clear();
            System.out.println("Final Check:");

            for (int i = 0; i < masterTimes.size(); i++){
                System.out.println(i + " | " + masterTimes.get(i) + " | " + temp2[i]);
            }

        }
}
0 голосов
/ 02 февраля 2011

Вот решение R.

Раскомментируйте две строки install.packages, если эти пакеты еще не установлены. Кроме того, textConnection(Lines1) и textConnection(Lines2) предназначены только для того, чтобы оставить пример самодостаточным, и в действительности его можно заменить на что-то вроде "myfile1.dat" и "myfile2.dat", предполагая, что данные находятся в этих файлах.

Считывает в данных создания зоопарка объект z и вектор даты dt. Затем он объединяет z с объектом зоопарка нулевой ширины (т. Е. У него есть даты, но нет данных), чей индекс даты сделан из dt. na.locf (последнее перенесенное наблюдение) заполняет пропущенные значения в обратном порядке, поскольку fromLast = TRUE

Lines1 <- "Date           Price
1/3/2000        10.00
1/5/2000        10.45
1/7/2000        10.25"

Lines2 <- "Date
1/1/2000
1/2/2000
1/3/2000"

# install.packages("zoo")
# install.packages("chron")
library(zoo)
library(chron)
z <- read.zoo(textConnection(Lines1), header = TRUE, FUN = as.chron)
dt <- as.chron(scan(textConnection(Lines2), skip = 1, what = ""))
na.locf(merge(z, zoo(, dt)), fromLast = TRUE)

Результат:

> na.locf(merge(z, zoo(, dt)), fromLast = TRUE)
01/01/00 01/02/00 01/03/00 01/05/00 01/07/00 
   10.00    10.00    10.00    10.45    10.25 

Есть три виньетки (документы в формате PDF), которые поставляются с зоопарком и R News 4/1 Статья службы поддержки содержит информацию и ссылки на даты.

0 голосов
/ 02 февраля 2011

Ладно ... Я просто стреляю в него, когда нахожусь на телефоне:)

Предположим, что в MySQL у вас есть две таблицы: date_prices и all_dates. Затем оставьте их на даты и упорядочите по дате.

Если вы используете R и MySQL, вы можете использовать пакет RMySQL для загрузки результирующей таблицы в R. В R вы можете конвертировать даты в POSIX с as.POSIXlt. Вы также можете захотеть использовать функцию lag в R (но я пока не уверен, поможет ли это с запаздыванием в различных диапазонах).

Кроме того, вы можете использовать пакет R's´sqldf`, если вы хотите попробовать "обычный" R, но хотите использовать функциональность SQL. Если вы разместите некоторый воспроизводимый код для настройки данных ... Я мог бы попытаться дать что-то более конкретное.

РЕДАКТИРОВАТЬ:

Пакет impute может быть тем, что вы действительно ищете ... см. Также здесь

0 голосов
/ 02 февраля 2011

Для правильной работы такого рода проблем требуется определенное время. Иногда использование блок-схемы помогает, если вы застряли.

Попробуйте использовать следующий пример кода:

import java.sql.*;
import java.util.*;

public class FillDates
{
    public static void fillUnknownDates(Connection c) throws SQLException
    {
        // Loads in a Vector of Strings of all the dates
        Statement state = c.createStatement();
        ResultSet results = state.executeQuery("SELECT d FROM Dates ORDER BY d;");
        Vector<String> dates = new Vector<String>();
        while (results.next())
        {
            dates.add(results.getString("d"));
        }

        // Load in a list of all date/price combinations
        Vector<DatePrice> pairs = new Vector<DatePrice>();
        state = c.createStatement();
        results = state.executeQuery("SELECT d, p FROM DatePrices ORDER BY d;");
        while (results.next())
        {
            pairs.add(new DatePrice(results.getString("d"), results.getString("p")));
        }

        // Now go through the two lists and add missing prices
        state = c.createStatement();
        int dateIndex = 0;
        DatePrice last = pairs.get(0), current;
        for (int pairIndex = 1; pairIndex < pairs.size(); pairIndex++)
        {
            current = pairs.get(pairIndex);
            while (dateIndex < dates.size() && dates.get(dateIndex).compareTo(current.getDate()) < 0)
            {
                // Batch things up so it takes less time to run
                state.addBatch("INSERT INTO DatePrices VALUES (\""+dates.get(dateIndex)+"\", \""+current.getPrice+"\");");
                dateIndex ++;
            }

            last = current;
        }
        state.executeBatch();
    }

    // A convenience class
    public static class DatePrice
    {
        private String date, price;

        public DatePrice(String date, String price)
        {
            this.date = date;
            this.price = price;
        }
        public String getDate()
        {
            return date;
        }
        public String getPrice()
        {
            return price;
        }
    }
}

Обратите внимание, что это не завершено, и вам нужно изменить имена таблиц и столбцов, прежде чем испытать это.

0 голосов
/ 02 февраля 2011

Трудно помочь, не глядя на код, но кажется, что ваши индексы не совпадают или что-то не так с вашей логикой зацикливания.

Рассмотрите возможность использования HashTable или HashMap, используя строки даты какключи и цена в виде значений.

Перебирайте диапазон дат один день за разом, ищите цену в HashTable, если она не найдена, используйте предыдущую цену.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...