Бросок моей шляпы в:
library(Rcpp)
cppFunction('IntegerVector na_locf(IntegerVector x) {
int n = x.size();
for(int i = 0; i<n; i++) {
if((i > 0) && (x[i] == NA_INTEGER) & (x[i-1] != NA_INTEGER)) {
x[i] = x[i-1];
}
}
return x;
}')
Настройте базовый образец и контрольный показатель:
x <- sample(c(1,2,3,4,NA))
bench_em <- function(x,count = 10) {
x <- sample(x,count,replace = TRUE)
print(microbenchmark(
na_locf(x),
replace_na_with_last(x),
na.lomf(x),
na.locf(x),
repeat.before(x)
), order = "mean", digits = 1)
}
И запустите несколько этапов:
bench_em(x,1e6)
Unit: microseconds
expr min lq mean median uq max neval
na_locf(x) 697 798 821 814 821 1e+03 100
na.lomf(x) 3511 4137 5002 4214 4330 1e+04 100
replace_na_with_last(x) 4482 5224 6473 5342 5801 2e+04 100
repeat.before(x) 4793 5044 6622 5097 5520 1e+04 100
na.locf(x) 12017 12658 17076 13545 19193 2e+05 100
На всякий случай:
all.equal(
na_locf(x),
replace_na_with_last(x),
na.lomf(x),
na.locf(x),
repeat.before(x)
)
[1] TRUE
Для числового вектора функция немного отличается:
NumericVector na_locf_numeric(NumericVector x) {
int n = x.size();
LogicalVector ina = is_na(x);
for(int i = 1; i<n; i++) {
if((ina[i] == TRUE) & (ina[i-1] != TRUE)) {
x[i] = x[i-1];
}
}
return x;
}
Если у вас есть одинаковые столбцы во всех файлах csv
, вы можете попробовать код ниже. Я добавил header=0
, чтобы после чтения csv
первая строка могла быть назначена как имена столбцов.
path =r'C:\DRO\DCL_rawdata_files' # use your path
allFiles = glob.glob(path + "/*.csv")
frame = pd.DataFrame()
list_ = []
for file_ in allFiles:
df = pd.read_csv(file_,index_col=None, header=0)
list_.append(df)
frame = pd.concat(list_)
Альтернатива ответам darindaCoder :
path = r'C:\DRO\DCL_rawdata_files' # use your path
all_files = glob.glob(os.path.join(path, "*.csv")) # advisable to use os.path.join as this makes concatenation OS independent
df_from_each_file = (pd.read_csv(f) for f in all_files)
concatenated_df = pd.concat(df_from_each_file, ignore_index=True)
# doesn't create a list, nor does it append to one
pd.concat(pd.read_csv(f) for f in all_files)
.
– Mike
21 June 2016 в 20:28
glob.iglob
вместо glob.glob
; Первый возвращает и итератор (вместо списка) .
– toto_tico
2 August 2017 в 12:52
import glob, os
df = pd.concat(map(pd.read_csv, glob.glob(os.path.join('', "my_files*.csv"))))
df = pd.concat(map(lambda file: pd.read_csv(file, delim_whitespace=True), data_files))
– fiedl
11 April 2018 в 14:46
Библиотека Dask может считывать данные из нескольких файлов:
>>> import dask.dataframe as dd
>>> df = dd.read_csv('data*.csv')
(Источник: http://dask.pydata.org/en/latest/examples/dataframe-csv. html )
Dataframes Dask реализует подмножество API-интерфейсов данных Pandas. Если все данные вписываются в память, вы можете вызвать df.compute()
, чтобы преобразовать данные в рамку данных Pandas.
Если несколько файлов csv заархивированы, вы можете использовать zip-файл для чтения всех и конкатенации, как показано ниже:
import zipfile
import numpy as np
import pandas as pd
ziptrain = zipfile.ZipFile('yourpath/yourfile.zip')
train=[]
for f in range(0,len(ziptrain.namelist())):
if (f == 0):
train = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
else:
my_df = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
train = (pd.DataFrame(np.concatenate((train,my_df),axis=0),
columns=list(my_df.columns.values)))
filepaths = ['data/d1.csv', 'data/d2.csv','data/d3.csv','data/d4.csv']
df = pd.concat(map(pd.read_csv, filepaths))
Изменить: я googled мой путь в https://stackoverflow.com/a/21232849/186078 . Однако в последнее время я нахожу быстрее выполнять любые манипуляции с помощью numpy, а затем назначая его один раз в dataframe, а не манипулируя самим фреймворком на итеративной основе, и, похоже, он тоже работает в этом решении.
искренне хочу, чтобы кто-то нажал эту страницу, чтобы рассмотреть этот подход, но не хочу прикладывать эту огромную часть кода в качестве комментария и сделать его менее читаемым.
Вы можете использовать numpy, чтобы действительно ускорить конкатенацию файловой системы.
import os
import glob
import pandas as pd
import numpy as np
path = "my_dir_full_path"
allFiles = glob.glob(os.path.join(path,"*.csv"))
np_array_list = []
for file_ in allFiles:
df = pd.read_csv(file_,index_col=None, header=0)
np_array_list.append(df.as_matrix())
comb_np_array = np.vstack(np_array_list)
big_frame = pd.DataFrame(comb_np_array)
big_frame.columns = ["col1","col2"....]
Статистика синхронизации:
total files :192
avg lines per file :8492
--approach 1 without numpy -- 8.248656988143921 seconds ---
total records old :1630571
--approach 2 with numpy -- 2.289292573928833 seconds ---
allfiles
, должен быть allFiles
– Ted Taylor of Life
13 July 2017 в 18:36
Если вы хотите искать рекурсивно ( Python 3.5 или выше ), вы можете сделать следующее:
import glob, os
import pandas as pd
path = r'C:\user\your\path\**'
all_rec = glob.iglob(os.path.join(path, "*.csv"), recursive=True)
dataframes = (pd.read_csv(f) for f in all_rec)
big_dataframe = pd.concat(dataframes, ignore_index=True)
Вы можете найти документацию **
здесь . Кроме того, я использовал iglob
вместо glob
, поскольку он возвращает итератор вместо списка.
frame = pd.DataFrame()
? – FooBar 17 September 2014 в 16:03df = pd.concat((pd.read_csv(f) for f in all_files))
Кроме того, следует использоватьos.path.join(path, "*.csv")
вместоpath + "/*.csv"
, что делает его независимым от ОС. – Sid 23 January 2016 в 01:41pandas.read_csv(f).assign(filename = foo)
внутри генератора.assign
вернет весь фрейм данных, включая новый столбецfilename
– C8H10N4O2 4 April 2017 в 20:50