我有一份日期和价格清单:
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开放。感谢您的任何建议。
答案 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
与零宽度动物园对象合并(即它具有日期但没有数据),其日期索引来自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
zoo package和R News 4/1帮助台文章附带的三个小插图(PDF文档)包含有关日期的信息和参考。