Python 在一个数据帧中从多个.csv和cbind中提取相同的列(不同的长度)-R

Python 在一个数据帧中从多个.csv和cbind中提取相同的列(不同的长度)-R,python,r,financial,Python,R,Financial,因此,我有1300个以下格式的csv财务数据文件: Date Open High Low Close 1 Nov 28, 2017 0.233394 0.234871 0.223832 0.225542 2 Nov 27, 2017 0.225910 0.234219 0.212298 0.233113 3 Nov 26, 2017 0.229367 0.235126 0.215153 0.226367 4 Nov 25, 2017 0.23

因此,我有1300个以下格式的csv财务数据文件:

          Date     Open     High      Low    Close
1 Nov 28, 2017 0.233394 0.234871 0.223832 0.225542 
2 Nov 27, 2017 0.225910 0.234219 0.212298 0.233113
3 Nov 26, 2017 0.229367 0.235126 0.215153 0.226367
4 Nov 25, 2017 0.234212 0.239257 0.223383 0.228617
5 Nov 24, 2017 0.215836 0.236280 0.209834 0.234195
6 Nov 23, 2017 0.228887 0.232974 0.214334 0.216585
我的目标是从每个文件中提取“Open”列,并将这些列绑定在一起,使其看起来像这样:

     Date     "File1"   "File2"  "File3"  ... "File 1300"         
1 Nov 28, 2017 0.233394 0.234871 0.223832 ... 0.225542 
2 Nov 27, 2017 0.225910 0.234219 0.212298 ... 0.233117 
3 Nov 26, 2017 0.229367 0.235126 0.215153 ... 0.226367 
4 Nov 25, 2017 0.234212 NA       0.223383 ... 0.228617 
5 Nov 24, 2017 0.215836 NA       0.209834 ... 0.234195 
6 Nov 23, 2017 0.228887 NA       0.214334 ... NA
我知道这里已经有很多关于如何从多个csv文件中提取列以及如何将它们绑定在一起的问题,我几乎做到了,但问题是文件的长度不同,因为我根据日期进行了观察。例如,一个文件可以包含2014年Des 3的观察结果,而另一个文件可以包含2017年11月23日的观察结果。否则,这些文件在格式上是相同的,它们都在2017年11月28日进行了最后一次观察

下面你可以看到我的代码

# Get a List of all files in directory 
filenames <- list.files(".../path, pattern="*.csv", full.names=F)

# Loading column "Open" from each file 
for(i in filenames){   
    filepath <- file.path(".../path", paste(i,sep=""))   
    assign(i, read.csv(filepath, header=T, sep = ";", 
        colClasses=c(NA, NA, "NULL", "NULL", "NULL"))) 
}

#making a list of all data frames
df_list <- lapply(ls(), function(x) if (class(get(x)) == "data.frame") get(x)) 

#merging  
library(dplyr) 
res2 <- Reduce(function(...) left_join(..., by=c("Date")), df_list)
#获取目录中所有文件的列表

文件名这是未经测试的。关于如何导入的两种方法。一个是使用for循环进行迭代,而第二个是导入所有数据,然后使用
Reduce
合并2。对象到第一个,第三个到1的合并。和2,第四步合并1,2。三,。等等

# approach #1
result <- read.csv(filenames[1], header = TRUE, sep = ";")[, c("Date", "Open")]

for (i in filenames[-1]) {
  out <- read.csv(i, header = TRUE, sep = ";")[, c("Date", "Open")]
  colnames(out) <- c("Date", basename(filenames[i]))
  result <- merge(result, by = "Date")
}


# approach #2
alldata <- lapply(filenames, FUN = function(x) {
  out <- read.csv(i, header = TRUE, sep = ";")[, c("Date", "Open")]
  colnames(out) <- c("Date", basename(x))
  out
})

result <- Reduce(function(dtf1, dtf2) merge(dtf1, dtf2, by = "Date", all = TRUE), alldata)
方法1
结果如果您对Python的解决方案也感兴趣,请点击这里。我刚刚测试了它,它似乎有效:

首先,您需要将csv文件读入pandas中,假设列0、1是日期和打开的,
skipinitialspace=True
只是去掉了空白。由于我们需要一个包含数据帧的列表,我们在csv文件上循环:

dfs=[]
对于glob.glob('*.csv')中的文件:
追加(pd.read_csv(“./”+文件,分隔符=“;”,usecols=[0,1],skipinitialspace=True))
读取所有文件后,您希望更改列名,使其反映文件名:

dfs = [x.rename(columns={'Open': 'File_{}'.format(i)}) for i, x in enumerate(dfs)]
现在,礼貌地到这里来 您可以减少以创建最终数据帧:

df_final = reduce(lambda left,right: pd.merge(left,right,on='Date', how='outer'), dfs)

这将创建一个最终数据帧

这里是另一种使用时间序列库(
zoo
)的方法

首先,我将准备一些与您类似的数据:

library(quantmod)

getSymbols(c("MSFT","FB"),src='yahoo',from='2005-01-01')
MSFT=data.frame(Dt=strftime(time(MSFT),format = "%b %d, %Y"),
                Close=unname(MSFT[,"MSFT.Close"]))
rownames(MSFT)=NULL
FB=data.frame(Dt=strftime(time(FB),format = "%b %d, %Y"),
              Close=unname(FB[,"FB.Close"]))
rownames(FB)=NULL
write.csv(MSFT,file="MSFT.csv",row.names = FALSE)
write.csv(FB,file="FB.csv",row.names = FALSE)
现在来看看你问题的实际答案:

#answer to original question
library(zoo)

filenames=c("MSFT.csv","FB.csv")

finDataList=lapply(filenames,function(x) 
    read.csv.zoo(x,format="%b %d, %Y",drop=FALSE))

finData=do.call("merge",finDataList)
colnames(finData)=gsub("\\.csv","",filenames)
head(finData)
#             MSFT FB
# 2005-01-03 26.74 NA
# 2005-01-04 26.84 NA
# 2005-01-05 26.78 NA
# 2005-01-06 26.75 NA
# 2005-01-07 26.67 NA
# 2005-01-10 26.80 NA

谢谢你给我两个不同的选择。第一种方法似乎没有迭代所有文件,因为它只输出“out”作为第二个文件的数据。我认为第二种方法看起来更快,但当我遇到这个错误时,合并函数似乎无法识别“date”:“fix.by中的错误(by.x,x):“by”必须指定一个唯一有效的列”,这与我尝试初始方法时遇到的问题几乎相同。我想必须添加一个
return(out)
到2号进近的
lappy
功能。谢谢!这几乎解决了问题。我现在唯一的问题是日期顺序不正确。例如,我得到2017年8月的所有日期,然后是12月的所有日期等。我可以只按日期排序,但如果我能从一开始就以正确的顺序得到它,则会更整洁。我在任何地方都看不到日期转换,因此我假设行是通过将日期列解释为
字符
来排序的。您可以在日期列上尝试使用
strtime
,如
strtime(“2017年11月28日”,format=“%b%d,%Y”)
。您可能需要为缩写月份名称设置正确的区域设置。谢谢各位。日期列有点棘手,但将其从因子转换为字符,然后使用lubridate包将其转换为真实日期列解决了排序问题。我刚刚意识到,新列的后缀取决于列表中的位置,因此您可以检查文件是否按顺序放入列表中。就我而言,他们是。。。