извлечь один и тот же столбец (разной длины) из нескольких .csv и cbind в одном фрейме данных - R - PullRequest
0 голосов
/ 20 мая 2018

Итак, у меня есть 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

Моя цель - извлечь столбец «Открыть» из каждого файла и связать столбцы вместе, чтобы он выглядел как-товот так:

     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-файлов и как связать их вместе, и я почти у цели, но проблема в том,что длина файлов различна, так как у меня есть наблюдения, основанные на датах.Например, один файл может иметь наблюдения от 3 декабря 2014 года, а другой - от 23 ноября 2017 года. В противном случае файлы идентичны по формату, и все они имеют свое последнее наблюдение 28 ноября 2017 года.

Ниже вы можете увидеть мой код до сих пор

# 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)

Как вы можете видеть, я загружаю все csv-файлы в глобальную среду и делаю их в список, где я затем хочу объединитьстолбцы в один фрейм данных.Кажется, проблема заключается в слиянии, где пакет Reduce или dplyr, похоже, не решает проблему.

Поэтому мой вопрос заключается в том, есть ли у вас какие-либо решения для связывания столбцов со всеми столбцами даты в одномфрейм данных и сортировка по дате?А также, есть ли быстрое решение сделать имена файлов в качестве заголовков для столбцов?

Я также не уверен, что R - лучший способ решить эту проблему.Я не настолько знаком с Python, но если вы думаете, что это проще, я могу попробовать использовать это вместо этого.

Ответы [ 3 ]

0 голосов
/ 20 мая 2018

Если вы также заинтересованы в решении на Python, пожалуйста.Я только что проверил это, и похоже, что оно работает:

Прежде всего вам нужно прочитать csv-файлы в панды, предполагая, что столбцы 0, 1 - это Date и Open, skipinitialspace=True просто избавляется от пробелов,Поскольку нам нужен список, содержащий кадры данных, мы перебираем файлы csv:

dfs = []
for files in glob.glob('*.csv'):
    dfs.append(pd.read_csv('./' + files, delimiter=';', 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)

Это создаст окончательный фрейм данных

0 голосов
/ 20 мая 2018

Здесь другой подход с использованием библиотеки временных рядов (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
0 голосов
/ 20 мая 2018

Это не проверено.Два подхода к импорту.Один является итеративным с циклом for, в то время как второй импортирует все данные, а затем использует Reduce для объединения 2. объект в первый, третий для объединения 1. и 2., затем для объединения 1., 2. и 3и т. д.

# 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)
...