Python 在一个数据帧中从多个.csv和cbind中提取相同的列(不同的长度)-R
因此,我有1300个以下格式的csv财务数据文件: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
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包将其转换为真实日期列解决了排序问题。我刚刚意识到,新列的后缀取决于列表中的位置,因此您可以检查文件是否按顺序放入列表中。就我而言,他们是。。。