填写表格上的缺失值

时间:2011-02-02 06:31:30

标签: java mysql r jdbc

我有一份日期和价格清单:

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 个答案:

答案 0 :(得分:1)

感谢大家的帮助。这是我最终做的事情: - 我创建了日期匹配的所有索引的列表 - 然后我将价格插入到一个数组中,该数组具有与完整时间列表相同数量的元素。 - 然后我创建了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]);
            }

        }
}

答案 1 :(得分:0)

如果没有查看代码,很难提供帮助,但看起来您的索引不匹配或者循环逻辑出现问题。

考虑使用HashTable或HashMap,使用日期字符串作为键,并将价格作为值。

一天一天在您的日期范围内循环查看HashTable中的价格,如果没有找到,则使用之前的价格。

答案 2 :(得分:0)

好吧......我只是在fon上拍摄它:)

在MySQL中,我们假设你有两个表,date_prices和all_dates。然后LEFT在日期加入它们并按日期排序。

如果使用R和MySQL,可以使用RMySQL包将结果表加载到R. 在R中,您可以使用as.POSIXlt将日期转换为POSIX。您也可能希望在R中使用lag函数(但我不确定这是否有助于不同跨度的滞后)。

除此之外,如果你想尝试使用“普通”R但是想要使用SQL功能,你可以使用R's的qldf`包。如果您发布一些可重现的代码来设置数据..我可以尝试给出更具体的内容。

编辑:

impute包可能是您真正想要的...另请参阅here

答案 3 :(得分:0)

这类问题确实需要做一些正确的事情。如果你遇到问题,有时使用流程图会有所帮助。

尝试使用以下示例代码:

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;
        }
    }
}

请注意,它不完整,您需要在尝试之前更改表和列的名称。

答案 4 :(得分:0)

这是一个R解决方案。

如果您尚未安装这些软件包,请取消注释两个install.packages行。此外,textConnection(Lines1)textConnection(Lines2)只是为了让示例自包含,并且实际上将替换为"myfile1.dat""myfile2.dat"之类的内容,假设数据位于这些文件中。

它读入创建动物园对象z的数据和日期向量dt。然后它将z与零宽度动物园对象合并(即它具有日期但没有数据),其日期索引来自dtna.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 

zoo packageR News 4/1帮助台文章附带的三个小插图(PDF文档)包含有关日期的信息和参考。