2017-10-22 102 views
0

我想写一个python脚本来检查是否有缺失的一天。如果有的话,应该从最新的一天拿走价格,并创造一个新的数据日。我的意思是如下所示。我的数据在CSV文件中。任何想法如何做到?如何自动将数据添加到历史股票价格中缺失的日子?

前:

MSFT,5-Jun-07,259.16 
MSFT,3-Jun-07,253.28 
MSFT,1-Jun-07,249.95 
MSFT,31-May-07,248.71 
MSFT,29-May-07,243.31 

后:

MSFT,5-Jun-07,259.16 
MSFT,4-Jun-07,253.28 
MSFT,3-Jun-07,253.28 
MSFT,2-Jun-07,249.95 
MSFT,1-Jun-07,249.95 
MSFT,31-May-07,248.71 
MSFT,30-May-07,243.31 
MSFT,29-May-07,243.31 

我的解决办法:

import pandas as pd 
df = pd.read_csv("path/to/file/file.csv",names=list("abc")) # read string as file 


cols = df.columns # store column order 
df.b = pd.to_datetime(df.b) # convert col Date to datetime 
df.set_index("b",inplace=True) # set col Date as index 
df = df.resample("D").ffill().reset_index() # resample Days and fill values 

df = df[cols] # revert order 
df.sort_values(by="b",ascending=False,inplace=True) # sort by date 
df["b"] = df["b"].dt.strftime("%-d-%b-%y") # revert date format 
df.to_csv("data.csv",index=False,header=False) #specify outputfile if needed 

print(df.to_string()) 

回答

2

使用熊猫库此操作可在一个单一的线路进行说明。但首先,我们需要在数据读取到正确的格式:

import io 
import pandas as pd 

s = u"""name,Date,Close 
MSFT,30-Dec-16,771.82 
MSFT,29-Dec-16,782.79 
MSFT,28-Dec-16,785.05 
MSFT,27-Dec-16,791.55 
MSFT,23-Dec-16,789.91 
MSFT,16-Dec-16,790.8 
MSFT,15-Dec-16,797.85 
MSFT,14-Dec-16,797.07""" 

#df = pd.read_csv("path/to/file.csv") # read from file 
df = pd.read_csv(io.StringIO(s)) # read string as file 

cols = df.columns # store column order 
df.Date = pd.to_datetime(df.Date) # convert col Date to datetime 
df.set_index("Date",inplace=True) # set col Date as index 
df = df.resample("D").ffill().reset_index() # resample Days and fill values 

df 

返回:

  Date name Close 
0 2016-12-14 MSFT 797.07 
1 2016-12-15 MSFT 797.85 
2 2016-12-16 MSFT 790.80 
3 2016-12-17 MSFT 790.80 
4 2016-12-18 MSFT 790.80 
5 2016-12-19 MSFT 790.80 
6 2016-12-20 MSFT 790.80 
7 2016-12-21 MSFT 790.80 
8 2016-12-22 MSFT 790.80 
9 2016-12-23 MSFT 789.91 
10 2016-12-24 MSFT 789.91 
11 2016-12-25 MSFT 789.91 
12 2016-12-26 MSFT 789.91 
13 2016-12-27 MSFT 791.55 
14 2016-12-28 MSFT 785.05 
15 2016-12-29 MSFT 782.79 
16 2016-12-30 MSFT 771.82 

返回到CSV具有:

df = df[cols] # revert order 
df.sort_values(by="Date",ascending=False,inplace=True) # sort by date 
df["Date"] = df["Date"].dt.strftime("%-d-%b-%y") # revert date format 
df.to_csv(index=False,header=False) #specify outputfile if needed 

输出:

MSFT,30-Dec-16,771.82 
MSFT,29-Dec-16,782.79 
MSFT,28-Dec-16,785.05 
MSFT,27-Dec-16,791.55 
MSFT,26-Dec-16,789.91 
MSFT,25-Dec-16,789.91 
MSFT,24-Dec-16,789.91 
MSFT,23-Dec-16,789.91 
... 
+0

我有csv文件中的数据。有没有简单的方法来转换此解决方案从csv获取数据? – wahtdbogh

+0

是的,我试过了,但我得到了'提高ValueError(“未知字符串格式”) ValueError:未知字符串格式' – wahtdbogh

+0

我添加了示例CSV文件到更新的问题。 – wahtdbogh

0

要做到这一点,你需要使用嵌套的for循环通过你的数据帧进行迭代。这看起来是这样的:

for column in df: 
    for row in df: 
     do_something() 

为了给你一个想法,你的代码的

do_something() 

部分可能会是这样的检查是否有日期之间的差距。然后,你会从上面的行用复制等栏目,并插入一个新行:

df.loc[row] = [2, 3, 4] # adding a row 
df.index = df.index + 1 # shifting index 
df = df.sort() # sorting by index 

希望这有助于给你,你会如何解决这个问题的想法。让我知道你是否想要更多的代码!

0

此代码使用标准例程。

from datetime import datetime, timedelta 

输入行将不得不在逗号分割,并在代码的主要部分在两个地方解析日期。因此,我将这项工作放在一个单一的功能中。

def glean(s): 
    msft, date_part, amount = s.split(',') 
    if date_part.find('-')==1: 
     date_part = '0'+date_part 
    date = datetime.strptime(date_part, '%d-%b-%y') 
    return date, amount 

类似地,日期必须格式化以便在主代码中的许多位置输出其他数据。

def out(date,amount): 
    date_str = date.strftime('%d-%b-%y') 
    print(('%s,%s,%s' % ('MSFT', date_str, amount)).replace('MSFT,0', 'MSFT,')) 

with open('before.txt') as before: 

我读了它自己的数据的初始行建立的第一个日期与日期下一行比较。

previous_date, previous_amount = glean(before.readline().strip()) 
out(previous_date, previous_amount) 
for line in before.readlines(): 
    date, amount = glean(line.strip()) 

我计算当前行和上一行之间的经过时间,以知道需要输出多少行代替缺少的行。

elapsed = previous_date - date 

setting_dateprevious_date递减几天,没有数据经过的数量。如果有的话,每天都会忽略一行。

setting_date = previous_date 
    for i in range(-1+elapsed.days): 
     setting_date -= timedelta(days=1) 
     out(setting_date, previous_amount) 

现在输出可用的数据行。

out(date, amount) 

现在previous_dateprevious_amount复位,以反映新值,针对数据的下一行使用,如果有的话。

previous_date, previous_amount = date, amount 

输出:

MSFT,5-Jun-07,259.16 
MSFT,4-Jun-07,259.16 
MSFT,3-Jun-07,253.28 
MSFT,2-Jun-07,253.28 
MSFT,1-Jun-07,249.95 
MSFT,31-May-07,248.71 
MSFT,30-May-07,248.71 
MSFT,29-May-07,243.31 
+0

我收到一个错误 - 'ValueError:时间数据'日期'不匹配格式' %d-%b-%y''也许从csv文件加载数据会更容易一些,因为此刻我在csv文件中有我的数据。我将我的源代码添加到更新后的问题中。任何建议可能是错误的? – wahtdbogh

+0

您可以使用您的csv文件,因为它们符合您问题中指出的格式。 (如果不是,所有投注都关闭!)我在使用该日期时间格式时略微避开了规则。规则没有吸引我,但他们抓住了你。我在编辑中添加了几行'glean'来处理这个问题。我也改变了实际上正确的输出。我在回答中提出了一个较早的(不正确的)版本。 –

+0

这可以用csv模块完成,但它不会更容易,可能会稍微难一些。 –