একবারে একাধিক .csv ফাইল কীভাবে আমদানি করবেন?


219

মনে করুন আমাদের কাছে একাধিক ডেটা। সিএসভি ফাইলযুক্ত ফোল্ডার রয়েছে, প্রতিটিতে একই সংখ্যক ভেরিয়েবল রয়েছে তবে প্রতিটি বিভিন্ন সময় থেকে রয়েছে। আর এগুলিকে পৃথকভাবে আমদানি করার পরিবর্তে এগুলি সব একই সাথে আমদানির কোনও উপায় আছে কি?

আমার সমস্যাটি হ'ল আমার কাছে প্রায় 2000 টি ডেটা ফাইল আমদানি করতে এবং কেবলমাত্র কোড ব্যবহার করে স্বতন্ত্রভাবে আমদানি করতে হবে:

read.delim(file="filename", header=TRUE, sep="\t")

খুব দক্ষ নয়।

উত্তর:


259

নীচের মতো কিছুতে প্রতিটি ডেটা ফ্রেমের একক তালিকার পৃথক উপাদান হিসাবে ফলাফল হওয়া উচিত:

temp = list.files(pattern="*.csv")
myfiles = lapply(temp, read.delim)

এই অনুমান আপনি একটি একক ডিরেক্টরির মধ্যে ঐ CSVs আছে - আপনার সাম্প্রতিক কাজ করা - এবং তাদের সব ছোট হাতের এক্সটেনশন আছে .csv

তারপরে আপনি যদি সেই ডেটা ফ্রেমগুলিকে একটি একক ডেটা ফ্রেমে একত্রিত করতে চান তবে do.call(rbind,...), dplyr::bind_rows()বা এর মতো জিনিসগুলি ব্যবহার করে অন্যান্য উত্তরের সমাধানগুলি দেখুন data.table::rbindlist()

আপনি যদি সত্যিই প্রতিটি ডেটা ফ্রেমকে একটি পৃথক অবজেক্টে চান তবে তা প্রায়শই অবিশ্বাস্যরূপে হওয়া সত্ত্বেও, আপনি নিম্নলিখিতগুলির সাথে এটি করতে পারেন assign:

temp = list.files(pattern="*.csv")
for (i in 1:length(temp)) assign(temp[i], read.csv(temp[i]))

অথবা, ছাড়াই assignএবং (1) ফাইলের নামটি কীভাবে পরিষ্কার করা যায় এবং (2) কীভাবে ব্যবহার list2envকরতে হয় তা দেখানোর জন্য , আপনি নিম্নলিখিতগুলি চেষ্টা করতে পারেন:

temp = list.files(pattern="*.csv")
list2env(
  lapply(setNames(temp, make.names(gsub("*.csv$", "", temp))), 
         read.csv), envir = .GlobalEnv)

তবে আবার তাদের একক তালিকায় রেখে দেওয়া প্রায়শই ভাল।


ধন্যবাদ! এটি খুব ভালভাবে কাজ করে ... আমি কেবলমাত্র আমদানি করা প্রতিটি ফাইলের নামকরণ কীভাবে করব যাতে আমি সহজেই তাদের কল করতে পারি?
জোজো ওনো

আপনি যদি আমাদের কিছু ফাইলের প্রথম কয়েকটি লাইন আমাদের দেখান তবে আমাদের কিছু পরামর্শ থাকতে পারে - এর জন্য আপনার প্রশ্নটি সম্পাদনা করুন!
স্পেসডম্যান

2
উপরের কোডগুলি একক বস্তু হিসাবে তাদের আমদানির জন্য নিখুঁতভাবে কাজ করে তবে আমি যখন ডেটা সেট থেকে একটি কলাম কল করার চেষ্টা করি তখন এটি এটি সনাক্ত করতে পারে না কারণ এটি কেবলমাত্র একটি একক বস্তু নয় যা কোনও ডেটা ফ্রেম নয় উপরের কোডটির আমার সংস্করণটি: সেটডউইড ( 'সি: / ব্যবহারকারী / নতুন / ডেস্কটপ / ডাইভস / 0904_003') টেম্প <-list.files (প্যাটার্ন = "*। সিএসভি") ডিডাইভস <- ল্যাপ্লি (টেম্প, রিড সিএসভি) তাই এখন প্রতিটি ফাইলকে ডাইডাইভ বলা হয় [এন ] তবে আমি কীভাবে একটি একক অবজেক্টের চেয়ে সমস্ত ডেটা ফ্রেম তৈরি করতে একটি লুপ লিখব? আমি ডেটা.ফ্রেম অপারেটরটি ব্যবহার করে স্বতন্ত্রভাবে এটি অর্জন করতে পারি তবে কীভাবে এটি লুপ করা যায় সে সম্পর্কে আমি অনিশ্চিত। @ মির্দবব
জোজো ওনো

@ জোসেফঅনুফ্রিউ, আমার আপডেট দেখুন। তবে সাধারণত, আমি তালিকাগুলির সাথে কাজ করা আরও সহজ মনে করি যদি আমি সমস্ত ডেটা ফ্রেমগুলিতে একই রকম গণনা করি।
A5C1D2H2I1M1N2O1R2T1

2
যে কেউ ব্যবহার করে এই উত্তরের আপডেট সংস্করণটি করার জন্য কোনও ফাংশন লেখার চেষ্টা করছেন assign... আপনি যদি নির্ধারিত মানগুলি বিশ্বব্যাপী পরিবেশে থাকতে চান তবে নিশ্চিত হয়ে নিন যে আপনি সেট করেছেন inherits=T
dnlbrky

127

একটি দ্রুত এবং সুসংহত tidyverseসমাধান: ( বেস আর এর চেয়ে দ্বিগুণের বেশি দ্রুত read.csv)

tbl <-
    list.files(pattern = "*.csv") %>% 
    map_df(~read_csv(.))

এবং ডেটা.ট্যাবস এর fread()এমনকি লোডের সময়গুলি অর্ধেক করে কেটে ফেলতে পারে। ( বেস আর বারের 1/4 বারের জন্য)

library(data.table)

tbl_fread <- 
    list.files(pattern = "*.csv") %>% 
    map_df(~fread(.))

stringsAsFactors = FALSEযুক্তি dataframe ফ্যাক্টর বিনামূল্যে রাখে, (এবং marbel পয়েন্ট আউট হিসাবে, ডিফল্ট সেটিং fread)

যদি টাইপকাস্টিংটি চটকদার হয়ে থাকে তবে আপনি সমস্ত কলামকে col_typesযুক্তির সাথে অক্ষর হিসাবে বাধ্য করতে পারেন ।

tbl <-
    list.files(pattern = "*.csv") %>% 
    map_df(~read_csv(., col_types = cols(.default = "c")))

যদি আপনি আপনার ফাইলগুলির তালিকাটি শেষ পর্যন্ত বাঁধাই করতে সাবডাইরেক্টরিগুলিতে ডুবতে চান তবে অবশ্যই সেই পথের নাম অন্তর্ভুক্ত করার পাশাপাশি আপনার তালিকায় তাদের সম্পূর্ণ নাম সহ ফাইলগুলি নিবন্ধভুক্ত করতে ভুলবেন না। এটি বাধ্যতামূলক কাজটিকে বর্তমান ডিরেক্টরিটির বাইরের দিকে যেতে দেয়। (পুরো পথের নামগুলি পাসপোর্টের মতো চালনা হিসাবে ডিরেক্টরি 'সীমানা' জুড়ে চলাচলের অনুমতি দেওয়ার জন্য চিন্তা করা))

tbl <-
    list.files(path = "./subdirectory/",
               pattern = "*.csv", 
               full.names = T) %>% 
    map_df(~read_csv(., col_types = cols(.default = "c"))) 

যেমন হ্যাডলি এখানে বর্ণনা করেছেন (প্রায় অর্ধেক নীচে):

map_df(x, f)কার্যকরভাবে একই do.call("rbind", lapply(x, f))....

বোনাস বৈশিষ্ট্য - নীচে মন্তব্যগুলিতে অনুরোধ রেকর্ডে ফাইলের নাম যুক্ত করে:
* filenameপ্রতিটি রেকর্ডে আসল যুক্ত করুন ।

কোড ব্যাখ্যা করেছে: টেবিলগুলির প্রাথমিক পাঠের সময় প্রতিটি রেকর্ডে ফাইলের নাম যুক্ত করার জন্য একটি ফাংশন তৈরি করুন। তারপরে সাধারণ ফাংশনের পরিবর্তে সেই ফাংশনটি ব্যবহার করুন read_csv()

read_plus <- function(flnm) {
    read_csv(flnm) %>% 
        mutate(filename = flnm)
}

tbl_with_sources <-
    list.files(pattern = "*.csv", 
               full.names = T) %>% 
    map_df(~read_plus(.))

(টাইপকাস্টিং এবং সাব-ডিরেক্টরী হ্যান্ডলিং পন্থাগুলিও read_plus()একইভাবে ফাংশনের অভ্যন্তরে পরিচালনা করা যেতে পারে যা উপরে প্রস্তাবিত দ্বিতীয় এবং তৃতীয় রূপগুলিতে চিত্রিত হয়েছে।)

### Benchmark Code & Results 
library(tidyverse)
library(data.table)
library(microbenchmark)

### Base R Approaches
#### Instead of a dataframe, this approach creates a list of lists
#### removed from analysis as this alone doubled analysis time reqd
# lapply_read.delim <- function(path, pattern = "*.csv") {
#     temp = list.files(path, pattern, full.names = TRUE)
#     myfiles = lapply(temp, read.delim)
# }

#### `read.csv()`
do.call_rbind_read.csv <- function(path, pattern = "*.csv") {
    files = list.files(path, pattern, full.names = TRUE)
    do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))
}

map_df_read.csv <- function(path, pattern = "*.csv") {
    list.files(path, pattern, full.names = TRUE) %>% 
    map_df(~read.csv(., stringsAsFactors = FALSE))
}


### *dplyr()*
#### `read_csv()`
lapply_read_csv_bind_rows <- function(path, pattern = "*.csv") {
    files = list.files(path, pattern, full.names = TRUE)
    lapply(files, read_csv) %>% bind_rows()
}

map_df_read_csv <- function(path, pattern = "*.csv") {
    list.files(path, pattern, full.names = TRUE) %>% 
    map_df(~read_csv(., col_types = cols(.default = "c")))
}

### *data.table* / *purrr* hybrid
map_df_fread <- function(path, pattern = "*.csv") {
    list.files(path, pattern, full.names = TRUE) %>% 
    map_df(~fread(.))
}

### *data.table*
rbindlist_fread <- function(path, pattern = "*.csv") {
    files = list.files(path, pattern, full.names = TRUE)
    rbindlist(lapply(files, function(x) fread(x)))
}

do.call_rbind_fread <- function(path, pattern = "*.csv") {
    files = list.files(path, pattern, full.names = TRUE)
    do.call(rbind, lapply(files, function(x) fread(x, stringsAsFactors = FALSE)))
}


read_results <- function(dir_size){
    microbenchmark(
        # lapply_read.delim = lapply_read.delim(dir_size), # too slow to include in benchmarks
        do.call_rbind_read.csv = do.call_rbind_read.csv(dir_size),
        map_df_read.csv = map_df_read.csv(dir_size),
        lapply_read_csv_bind_rows = lapply_read_csv_bind_rows(dir_size),
        map_df_read_csv = map_df_read_csv(dir_size),
        rbindlist_fread = rbindlist_fread(dir_size),
        do.call_rbind_fread = do.call_rbind_fread(dir_size),
        map_df_fread = map_df_fread(dir_size),
        times = 10L) 
}

read_results_lrg_mid_mid <- read_results('./testFolder/500MB_12.5MB_40files')
print(read_results_lrg_mid_mid, digits = 3)

read_results_sml_mic_mny <- read_results('./testFolder/5MB_5KB_1000files/')
read_results_sml_tny_mod <- read_results('./testFolder/5MB_50KB_100files/')
read_results_sml_sml_few <- read_results('./testFolder/5MB_500KB_10files/')

read_results_med_sml_mny <- read_results('./testFolder/50MB_5OKB_1000files')
read_results_med_sml_mod <- read_results('./testFolder/50MB_5OOKB_100files')
read_results_med_med_few <- read_results('./testFolder/50MB_5MB_10files')

read_results_lrg_sml_mny <- read_results('./testFolder/500MB_500KB_1000files')
read_results_lrg_med_mod <- read_results('./testFolder/500MB_5MB_100files')
read_results_lrg_lrg_few <- read_results('./testFolder/500MB_50MB_10files')

read_results_xlg_lrg_mod <- read_results('./testFolder/5000MB_50MB_100files')


print(read_results_sml_mic_mny, digits = 3)
print(read_results_sml_tny_mod, digits = 3)
print(read_results_sml_sml_few, digits = 3)

print(read_results_med_sml_mny, digits = 3)
print(read_results_med_sml_mod, digits = 3)
print(read_results_med_med_few, digits = 3)

print(read_results_lrg_sml_mny, digits = 3)
print(read_results_lrg_med_mod, digits = 3)
print(read_results_lrg_lrg_few, digits = 3)

print(read_results_xlg_lrg_mod, digits = 3)

# display boxplot of my typical use case results & basic machine max load
par(oma = c(0,0,0,0)) # remove overall margins if present
par(mfcol = c(1,1)) # remove grid if present
par(mar = c(12,5,1,1) + 0.1) # to display just a single boxplot with its complete labels
boxplot(read_results_lrg_mid_mid, las = 2, xlab = "", ylab = "Duration (seconds)", main = "40 files @ 12.5MB (500MB)")
boxplot(read_results_xlg_lrg_mod, las = 2, xlab = "", ylab = "Duration (seconds)", main = "100 files @ 50MB (5GB)")

# generate 3x3 grid boxplots
par(oma = c(12,1,1,1)) # margins for the whole 3 x 3 grid plot
par(mfcol = c(3,3)) # create grid (filling down each column)
par(mar = c(1,4,2,1)) # margins for the individual plots in 3 x 3 grid
boxplot(read_results_sml_mic_mny, las = 2, xlab = "", ylab = "Duration (seconds)", main = "1000 files @ 5KB (5MB)", xaxt = 'n')
boxplot(read_results_sml_tny_mod, las = 2, xlab = "", ylab = "Duration (milliseconds)", main = "100 files @ 50KB (5MB)", xaxt = 'n')
boxplot(read_results_sml_sml_few, las = 2, xlab = "", ylab = "Duration (milliseconds)", main = "10 files @ 500KB (5MB)",)

boxplot(read_results_med_sml_mny, las = 2, xlab = "", ylab = "Duration (microseconds)        ", main = "1000 files @ 50KB (50MB)", xaxt = 'n')
boxplot(read_results_med_sml_mod, las = 2, xlab = "", ylab = "Duration (microseconds)", main = "100 files @ 500KB (50MB)", xaxt = 'n')
boxplot(read_results_med_med_few, las = 2, xlab = "", ylab = "Duration (seconds)", main = "10 files @ 5MB (50MB)")

boxplot(read_results_lrg_sml_mny, las = 2, xlab = "", ylab = "Duration (seconds)", main = "1000 files @ 500KB (500MB)", xaxt = 'n')
boxplot(read_results_lrg_med_mod, las = 2, xlab = "", ylab = "Duration (seconds)", main = "100 files @ 5MB (500MB)", xaxt = 'n')
boxplot(read_results_lrg_lrg_few, las = 2, xlab = "", ylab = "Duration (seconds)", main = "10 files @ 50MB (500MB)")

মিডল্লিং ইউজ কেস

বক্সপ্লট অতিবাহিত সময়ের তুলনা আমার সাধারণ ব্যবহারের ক্ষেত্রে

বড় ব্যবহারের কেস

অতিরিক্ত বড় লোডের জন্য অতিবাহিত সময়ের সাথে বক্সপ্লটের তুলনা

ব্যবহারের ক্ষেত্রে বিভিন্ন ধরণের

সারি: ফাইল গণনা (1000, 100, 10)
কলাম: চূড়ান্ত ডেটাফ্রেম আকার (5MB, 50MB, 500MB)
(মূল আকার দেখতে চিত্রটিতে ক্লিক করুন) ডিরেক্টরি আকারের পার্থক্যের তুলনা বক্সপ্লট

বৃহত্তর স্কেল প্রসেসিংয়ের কাজ সম্পাদন করার সময় পরিলক্ষিত পারফরম্যান্সের তুলনায় সিআর লাইব্রেরিগুলি সিআর লাইব্রেরিগুলি আনার ওভারহেডগুলি সবচেয়ে ছোট ব্যবহারের ক্ষেত্রে বেজ আর ফলাফলগুলি আরও ভাল।

আপনি যদি নিজের পরীক্ষা চালাতে চান তবে আপনি এই ব্যাশ স্ক্রিপ্টটিকে সহায়ক বলে মনে করতে পারেন।

for ((i=1; i<=$2; i++)); do 
  cp "$1" "${1:0:8}_${i}.csv";
done

bash what_you_name_this_script.sh "fileName_you_want_copied" 100 ক্রম অনুসারে আপনার ফাইলের 100 টি অনুলিপি তৈরি করবে (ফাইলের প্রাথমিক 8 টি অক্ষর এবং একটি আন্ডারস্কোরের পরে)।

গুণাবলী এবং প্রশংসা

বিশেষ ধন্যবাদ সাথে:

  • টাইলার রিঙ্কার এবং আকরুন প্রদর্শনের জন্য আকরুন।
  • আমাকে এখানে পরিচয় করানোর জন্য জ্যাক কাউপmap_df()
  • ডেভিড ম্যাকলফলিন ভিজ্যুয়ালাইজেশনের উন্নতি এবং ছোট ফাইল, ছোট ডেটাফ্রেম বিশ্লেষণ ফলাফলের মধ্যে পরিলক্ষিত পারফরম্যান্স উল্টোপাল্টা নিয়ে আলোচনা / নিশ্চিত করার বিষয়ে সহায়ক প্রতিক্রিয়ার জন্য।
  • জন্য ডিফল্ট আচরণ নির্দেশ করে জন্য মার্বেল fread()। (আমি পড়াশোনা করা প্রয়োজন data.table।)

1
আপনি সমাধান আমার জন্য কাজ করে। এর মধ্যে আমি সেই ফাইলের নামটি তাদের পার্থক্য রাখতে সঞ্চয় করতে চাই .. এটি কি সম্ভব?
নিক্স

1
@ নিকস - অবশ্যই! একটি সামান্য ফাংশনে কেবল লিখুন এবং অদলবদল করুন যা কেবল ফাইলগুলিই পড়ে না ততক্ষণে প্রতিটি রেকর্ড পঠনের সাথে সাথে একটি ফাইলের নাম সংযুক্ত করে name ভালো লেগেছে readAddFilename <- function(flnm) { read_csv(flnm) %>% mutate(filename = flnm) }তারপরে কেবল map_dfসেই সরল পঠনের পরিবর্তে কেবল read_csv()সেখানেই ফেলে দিন। আমি ফাংশনটি দেখানোর জন্য উপরের এন্ট্রিটি আপডেট করতে পারি এবং যদি আপনার এখনও প্রশ্ন থাকে বা আপনি মনে করেন যে এটি সহায়ক হবে the
leerssej

অনুশীলনে সমস্যাটি এটি read_csvতুলনায় অনেক ধীর fread। আপনি যদি কিছু দ্রুত বলতে চান তবে আমি একটি মানদণ্ড অন্তর্ভুক্ত করব। একটি ধারণা 30 1 গিগাবাইট ফাইল তৈরি করছে এবং সেগুলি পড়ছে, এটি এমন কোনও ক্ষেত্রে যেখানে কর্মক্ষমতা গুরুত্বপূর্ণ matters
মার্বেল

@ মার্বেল: পরামর্শের জন্য আপনাকে ধন্যবাদ! উপর 530 মেগাবাইট এবং ছোট ডিরেক্টরি (100 ফাইলগুলির সাথে) আমি মধ্যে কর্মক্ষমতা একটি 25% উন্নতি খোঁজার করছি data.table এর fread()এবং dplyr এর read_csv(): 14.2 বনাম 19.9 সেকেন্ড। টিবিএইচ, আমি কেবল বেস পি আর ডিপ্লাইয়ারের সাথে তুলনা করেছিলাম এবং read_csv()প্রায় 2-4x দ্রুত হিসাবে read.csv()বেঞ্চমার্কিং প্রয়োজনীয় বলে মনে হচ্ছে না। তবে fread()আরও সম্পূর্ণ বেঞ্চমার্ক ফলাফলগুলি পরীক্ষা করার জন্য ঘূর্ণি দেওয়া এবং বিরতি দেওয়া আকর্ষণীয় হয়েছে । আবার ধন্যবাদ!
leerssej

1
আর একটি দুর্দান্ত বিষয়। আমার মনে হয় যখন আমি লিখেছিলাম যে আমি ডেটা সংরক্ষণের বিষয়ে কিছুটা সচেতন ছিলাম able টেবিলের ক্রিয়াকলাপগুলিকে স্থানে ডেটাটি পরিবর্তন করা থেকে (যা পরবর্তী এবং পরবর্তী সমস্ত ডেটা জুড়ে সঞ্চালনকে প্রভাবিত করে)। অবশ্যই এই উদাহরণটি বোঝায় না। ধন্যবাদ. :-D খুব শীঘ্রই ফাংশন ছাড়াই এবং বড় মেশিনের সাথে আরও বড় ডেটাসেটের সাথে আবার সংখ্যা চালানোর প্রত্যাশায়।
লেয়ারসেজ

104

আর বেস ব্যবহার করে .csv ফাইলগুলিকে একটি ডেটা.ফ্রেমে রূপান্তর করার জন্য কয়েকটি বিকল্প রয়েছে এবং আর-তে ফাইলগুলি পড়ার জন্য উপলব্ধ কিছু প্যাকেজ রয়েছে using

এটি নীচের বিকল্পগুলির চেয়ে ধীর।

# Get the files names
files = list.files(pattern="*.csv")
# First apply read.csv, then rbind
myfiles = do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))

সম্পাদনা: - আরো কয়েকটি অতিরিক্ত ব্যবহার পছন্দ data.tableএবংreadr

একটি fread()সংস্করণ, যা data.tableপ্যাকেজের একটি ফাংশন । এটি আর এর মধ্যে সবচেয়ে দ্রুত বিকল্প

library(data.table)
DT = do.call(rbind, lapply(files, fread))
# The same using `rbindlist`
DT = rbindlist(lapply(files, fread))

রিডার ব্যবহার করে , যা সিএসভি ফাইলগুলি পড়ার জন্য অন্য প্যাকেজ। এটি freadবেস আর এর চেয়ে ধীর , তবে বিভিন্ন কার্যকারিতা রয়েছে।

library(readr)
library(dplyr)
tbl = lapply(files, read_csv) %>% bind_rows()

2
এটি কীভাবে বনাম হ্রাস (rbind, lapply (...)) সম্পাদন করে? কেবল আর শিখছি তবে আমার অনুমান কম পারফর্ম্যান্ট
অ্যারন

4
আমি একটি data.tableসংস্করণ যুক্ত করেছি , এর কর্মক্ষমতা উন্নত করা উচিত।
মার্বেল

কেবলমাত্র নির্দিষ্ট ফাইলগুলি পড়া কি সম্ভব? প্রাক্তন নামে 'আবহাওয়া' রয়েছে এমন ফাইলগুলি?
8:46

1
এটি এখানে খুঁজে পেয়েছে: stackoverflow.com/questions/10353540/… ধন্যবাদ।
ডিসি্লিক্ট

1
+1 একটি একক ডেটা ফ্রেম তৈরি করার মতো বলে মনে হচ্ছে - সমস্ত সিএসভি ফাইলের এসকিউএল ইউনিয়ন - এর সাথে কাজ করা সবচেয়ে সহজ। যেহেতু ওপি 1 টি ফ্রেম বা অনেকগুলি ডেটা ফ্রেম চায় কিনা তা নির্দিষ্ট করে দেয় না, তাই আমি ধরে নিয়েছিলাম 1 ডেটা ফ্রেম সবচেয়ে ভাল, তাই আমি অবাক হয়েছি গৃহীত উত্তরটি "ইউনিয়ন" এর কোনওটিই করে না। আমি এই উত্তরটি পছন্দ করি, যা এই ব্যাখ্যারdo.call
দ্য রেড মটরটি

24

পাশাপাশি ব্যবহার lapply বা অন্য কিছু লুপিং কনস্ট্রাক্ট আপনি নিজের সিএসভি ফাইলগুলিকে একটি ফাইলে মার্জ করতে পারেন।

ইউনিক্সে, যদি ফাইলগুলির কোনও শিরোনাম না থাকে তবে তার মতোই সহজ:

cat *.csv > all.csv

অথবা যদি এখানে শিরোনাম থাকে এবং আপনি একটি স্ট্রিং খুঁজে পেতে পারেন যা শিরোনাম এবং কেবলমাত্র শিরোনামের সাথে মেলে (যেমন ধরুন শিরোনামের রেখাগুলি সমস্ত "বয়স" দিয়ে শুরু হয়), আপনি যা করতে পারেন:

cat *.csv | grep -v ^Age > all.csv

আমি মনে করি উইন্ডোজে আপনি এটি দিয়ে এটি করতে পারেন COPY ডস কমান্ড বক্স থেকে এবং SEARCH(বা FINDকিছু) দিয়ে এটি করতে পারেন cygwinতবে ইউনিক্স কমান্ড শেলটি কেন ইনস্টল করে পাওয়ার পাবে না?


বা এমন কি গিট ব্যাশের সাথে যেতে পারেন যা Gitইনস্টলের সাথে কাঁপছে ?
leerssej

আমার অভিজ্ঞতা হিসাবে, যদি আপনার ফাইলগুলি আরও বড় হওয়া শুরু হয় তবে এটি সবচেয়ে দ্রুত সমাধান নয়।
আমির

20

এই কোডটি আমি সিএসভি ফাইলগুলি আর-তে পড়ার জন্য তৈরি করেছি! এটি প্রতিটি সিএসভি ফাইলের জন্য স্বতন্ত্রভাবে একটি ডেটাফ্রেম তৈরি করবে এবং শিরোনাম যা ফাইলটির মূল নাম (ফাঁকা স্থান এবং .csv অপসারণ) ডেটাফ্রেম করবে আশা করি আপনি এটি কার্যকর খুঁজে পেয়েছেন!

path <- "C:/Users/cfees/My Box Files/Fitness/"
files <- list.files(path=path, pattern="*.csv")
for(file in files)
{
perpos <- which(strsplit(file, "")[[1]]==".")
assign(
gsub(" ","",substr(file, 1, perpos-1)), 
read.csv(paste(path,file,sep="")))
}

8

@ A5C1D2H2I1M1N2O1R2T1, @leerssej, এবং @marbel দ্বারা শীর্ষ তিনটি উত্তর এবং সবগুলি মূলত একই: প্রতিটি ফাইলের জন্য ফ্রেড প্রয়োগ করুন, তারপরে ফলাফলগুলি ডেটা.টিবিলগুলি rbind / rbindlist করুন। আমি সাধারণত ব্যবহার করিrbindlist(lapply(list.files("*.csv"),fread)) ফর্মটি ।

এটি অন্যান্য আর-অভ্যন্তরীণ বিকল্পগুলির চেয়ে ভাল, এবং অল্প সংখ্যক বড় সিএসভি-র জন্য জরিমানা, তবে গতির ক্ষেত্রে যখন বড় সংখ্যক ছোট সিএসভি-র পক্ষে এটি সর্বোত্তম নয়। catসেক্ষেত্রে, @ স্পিডম্যান 4 র্থ স্থানে থাকা উত্তরে পরামর্শ হিসাবে এটি প্রথমে ব্যবহার করা আরও দ্রুত হতে পারে । আর এর মধ্যে থেকে কীভাবে এটি করা যায় সে সম্পর্কে আমি কিছু বিশদ যুক্ত করব:

x = fread(cmd='cat *.csv', header=F)

তবে, প্রতিটি সিএসভিতে যদি একটি শিরোনাম থাকে?

x = fread(cmd="awk 'NR==1||FNR!=1' *.csv", header=T)

এবং যদি আপনার কাছে *.csvএতগুলি ফাইল থাকে যে শেল গ্লোব ব্যর্থ হয়?

x = fread(cmd='find . -name "*.csv" | xargs cat', header=F)

এবং যদি সমস্ত ফাইলগুলির একটি শিরোনাম থাকে এবং সেখানে খুব বেশি ফাইল থাকে?

header = fread(cmd='find . -name "*.csv" | head -n1 | xargs head -n1', header=T)
x = fread(cmd='find . -name "*.csv" | xargs tail -q -n+2', header=F)
names(x) = names(header)

এবং যদি ফলাফলটির সাথে সংঘবদ্ধ সিএসভি সিস্টেম মেমোরির জন্য খুব বড় হয়?

system('find . -name "*.csv" | xargs cat > combined.csv')
x = fread('combined.csv', header=F)

হেডার সহ?

system('find . -name "*.csv" | head -n1 | xargs head -n1 > combined.csv')
system('find . -name "*.csv" | xargs tail -q -n+2 >> combined.csv')
x = fread('combined.csv', header=T)

অবশেষে, আপনি যদি কোনও ডিরেক্টরিতে সমস্ত .csv না চান, তবে ফাইলগুলির একটি নির্দিষ্ট সেট চান? (এছাড়াও, তাদের সবার শিরোনাম রয়েছে)) (এটি আমার ব্যবহারের ক্ষেত্রে)

fread(text=paste0(system("xargs cat|awk 'NR==1||$1!=\"<column one name>\"'",input=paths,intern=T),collapse="\n"),header=T,sep="\t")

এবং এটি প্লেইন ফ্রেড এক্সার্গস বিড়ালের মতো একই গতি :)

দ্রষ্টব্য: ডেটা.টিবলের জন্য প্রাক-v1.11.6 (19 সেপ্টেম্বর 2018), এর cmd=থেকে বাদ দিন fread(cmd=

সংযোজন: সিরিয়াল ল্যাপলির জায়গায় সমান্তরাল লাইব্রেরির এমক্ল্যাপ্লি ব্যবহার করা, যেমন, rbindlist(lapply(list.files("*.csv"),fread))rbindlist ল্যাপ্লি ফ্রেডের চেয়েও দ্রুত also

একক ডেটা.টিবেলে 121401 সিএসভি পড়ার সময়। প্রতিটি সিএসভিতে 3 টি কলাম, একটি শিরোনাম সারি এবং গড়ে গড়ে 4.510 সারি থাকে। মেশিনটি একটি জিসিপি ভিএম যা 96 টি কোর রয়েছে:

rbindlist lapply fread   234.172s 247.513s 256.349s
rbindlist mclapply fread  15.223s   9.558s   9.292s
fread xargs cat            4.761s   4.259s   5.095s

সংক্ষেপে, যদি আপনি গতির প্রতি আগ্রহী হন এবং অনেকগুলি ফাইল এবং অনেকগুলি কোর থাকে তবে ফ্রেড এক্সার্গস বিড়াল শীর্ষ 3 টির উত্তরের দ্রুত সমাধানের চেয়ে প্রায় 50x দ্রুত faster


6

আমার দৃষ্টিতে, অন্যান্য উত্তরগুলির বেশিরভাগই অপ্রচলিত rio::import_list, যা একটি সংযুক্ত একটি-লাইনার:

library(rio)
my_data <- import_list(dir("path_to_directory", pattern = ".csv", rbind = TRUE))

কোনও অতিরিক্ত যুক্তি পাস করা হয় rio::importrioপ্রায় কোনো ফাইল ফরম্যাট আর সাথে মোকাবিলা পড়তে পারেন করতে পারেন, এবং এটি ব্যবহার করে data.table'গুলি fread, যেখানে সম্ভব, তাই এটি দ্রুত খুব হওয়া উচিত।


5

plyr::ldplyপ্রায় .parallel400- সিসিভি ফাইলগুলি প্রায় 30-40 এমবি পড়ার সময় অপশনটি সক্ষম করে সেখানে প্রায় 50% গতি বৃদ্ধি পায় । উদাহরণে একটি পাঠ্য অগ্রগতি বার অন্তর্ভুক্ত রয়েছে।

library(plyr)
library(data.table)
library(doSNOW)

csv.list <- list.files(path="t:/data", pattern=".csv$", full.names=TRUE)

cl <- makeCluster(4)
registerDoSNOW(cl)

pb <- txtProgressBar(max=length(csv.list), style=3)
pbu <- function(i) setTxtProgressBar(pb, i)
dt <- setDT(ldply(csv.list, fread, .parallel=TRUE, .paropts=list(.options.snow=list(progress=pbu))))

stopCluster(cl)

চমৎকার উত্তর! আপনি কিভাবে অতিরিক্ত আর্গুমেন্ট পাস না freadবা user-defined functions? ধন্যবাদ!
টুং

1
@ টুংয়ের দিকে তাকিয়ে অন্যান্য যুক্তি ?ldplyদেখানো ...হয়েছে .fun। হয় fread, skip = 100বা function(x) fread(x, skip = 100)কাজ করে ব্যবহার করে
মনোটেশর্ক

ব্যবহার function(x) fread(x, skip = 100)আমার পক্ষে কাজ করে নি তবে খালি ফাংশন নামের পরে অতিরিক্ত আরগগুলি সরবরাহ করা কৌশলটি করেছে। আবার ধন্যবাদ!
টুং

3

Dnlbrk এর মন্তব্যে বিল্ডিং, অ্যাসাইন করা বড় ফাইলগুলির জন্য list2env এর চেয়ে যথেষ্ট দ্রুত হতে পারে।

library(readr)
library(stringr)

List_of_file_paths <- list.files(path ="C:/Users/Anon/Documents/Folder_with_csv_files/", pattern = ".csv", all.files = TRUE, full.names = TRUE)

পুরো.নাম আর্গুমেন্টটিকে সত্যে সেট করে, আপনি প্রতিটি ফাইলের সম্পূর্ণ পাথ আপনার ফাইলের তালিকায় পৃথক অক্ষরের স্ট্রিং হিসাবে পাবেন, যেমন, তালিকা_ফ_ফিল_প্যাথস [1] "সি: / ব্যবহারকারী / আনন / নথি / Folder_with_csv_files / file1.csv "

for(f in 1:length(List_of_filepaths)) {
  file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
  file_df <- read_csv(List_of_filepaths[f])  
  assign( x = file_name, value = file_df, envir = .GlobalEnv)
}

আপনি data_table প্যাকেজের ফ্রেড বা বেস r read.csv এর পরিবর্তে read_csv ব্যবহার করতে পারেন। ফাইল_নাম ধাপটি আপনাকে নামটি পরিষ্কার করার অনুমতি দেয় যাতে প্রতিটি ডাটা ফ্রেম নাম হিসাবে ফাইলের পুরো পথের সাথে না থাকে। আপনি বৈশ্বিক পরিবেশে স্থানান্তরিত করার আগে ডেটা টেবিলটিতে আরও জিনিসগুলি করতে আপনার লুপটি প্রসারিত করতে পারেন, উদাহরণস্বরূপ:

for(f in 1:length(List_of_filepaths)) {
  file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
  file_df <- read_csv(List_of_filepaths[f])  
  file_df <- file_df[,1:3] #if you only need the first three columns
  assign( x = file_name, value = file_df, envir = .GlobalEnv)
}

3

একাধিক ফাইল পড়তে এবং তাদের 1 ডেটা ফ্রেমে একত্রিত করার জন্য এটি আমার সুনির্দিষ্ট উদাহরণ:

path<- file.path("C:/folder/subfolder")
files <- list.files(path=path, pattern="/*.csv",full.names = T)
library(data.table)
data = do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))

1
আপনি rbindlist()থেকে ব্যবহার করতে পারেনdata.table
jogo

3

আপনার কম্পিউটারে অনেকগুলি কোর রয়েছে ততক্ষণ নীচের কোডগুলি আপনাকে বড় ডেটার জন্য দ্রুত গতি দেয়:

if (!require("pacman")) install.packages("pacman")
pacman::p_load(doParallel, data.table, stringr)

# get the file name
dir() %>% str_subset("\\.csv$") -> fn

# use parallel setting
(cl <- detectCores() %>%
  makeCluster()) %>%
  registerDoParallel()

# read and bind all files together
system.time({
  big_df <- foreach(
    i = fn,
    .packages = "data.table"
  ) %dopar%
    {
      fread(i, colClasses = "character")
    } %>%
    rbindlist(fill = TRUE)
})

# end of parallel work
stopImplicitCluster(cl)

2020/04/16 এ আপডেট হয়েছে: আমি যেমন সমান্তরাল গণনার জন্য একটি নতুন প্যাকেজ উপলভ্য পেয়েছি, নিম্নলিখিত কোডগুলি ব্যবহার করে একটি বিকল্প সমাধান সরবরাহ করা হবে।

if (!require("pacman")) install.packages("pacman")
pacman::p_load(future.apply, data.table, stringr)

# get the file name
dir() %>% str_subset("\\.csv$") -> fn

plan(multiprocess)

future_lapply(fn,fread,colClasses = "character") %>% 
  rbindlist(fill = TRUE) -> res

# res is the merged data.table

1

আমি ব্যবহার পদ্ধতির পছন্দ list.files(), lapply()এবং list2env()(অথবা fs::dir_ls(), purrr::map()এবংlist2env() )। এটি সহজ এবং নমনীয় বলে মনে হচ্ছে।

বিকল্পভাবে, আপনি ছোট প্যাকেজটি { টোর to ( টু-আর ) চেষ্টা করতে পারেন : ডিফল্টরূপে এটি ওয়ার্কিং ডিরেক্টরি থেকে ফাইলগুলি তালিকা ( list_*()বৈকল্পিক) বা বিশ্ব পরিবেশে আমদানি করে (load_*() রূপগুলি) ।

উদাহরণস্বরূপ, এখানে আমি আমার ওয়ার্কিং ডিরেক্টরি থেকে সমস্ত .csv ফাইলগুলি একটি তালিকায় ব্যবহার করে পড়ছি tor::list_csv():

library(tor)

dir()
#>  [1] "_pkgdown.yml"     "cran-comments.md" "csv1.csv"        
#>  [4] "csv2.csv"         "datasets"         "DESCRIPTION"     
#>  [7] "docs"             "inst"             "LICENSE.md"      
#> [10] "man"              "NAMESPACE"        "NEWS.md"         
#> [13] "R"                "README.md"        "README.Rmd"      
#> [16] "tests"            "tmp.R"            "tor.Rproj"

list_csv()
#> $csv1
#>   x
#> 1 1
#> 2 2
#> 
#> $csv2
#>   y
#> 1 a
#> 2 b

এবং এখন আমি এই ফাইলগুলিকে আমার বিশ্ব পরিবেশে লোড করছি tor::load_csv():

# The working directory contains .csv files
dir()
#>  [1] "_pkgdown.yml"     "cran-comments.md" "CRAN-RELEASE"    
#>  [4] "csv1.csv"         "csv2.csv"         "datasets"        
#>  [7] "DESCRIPTION"      "docs"             "inst"            
#> [10] "LICENSE.md"       "man"              "NAMESPACE"       
#> [13] "NEWS.md"          "R"                "README.md"       
#> [16] "README.Rmd"       "tests"            "tmp.R"           
#> [19] "tor.Rproj"

load_csv()

# Each file is now available as a dataframe in the global environment
csv1
#>   x
#> 1 1
#> 2 2
csv2
#>   y
#> 1 a
#> 2 b

আপনি নির্দিষ্ট ফাইল পড়া প্রয়োজন উচিত আপনার সাথে তাদের ফাইল পাথ মেলাতে পারে regexp, ignore.caseএবং invert


আরও নমনীয়তা ব্যবহারের জন্য list_any()। এটি আপনাকে আর্গুমেন্টের মাধ্যমে পাঠক ফাংশন সরবরাহ করতে দেয় .f

(path_csv <- tor_example("csv"))
#> [1] "C:/Users/LeporeM/Documents/R/R-3.5.2/library/tor/extdata/csv"
dir(path_csv)
#> [1] "file1.csv" "file2.csv"

list_any(path_csv, read.csv)
#> $file1
#>   x
#> 1 1
#> 2 2
#> 
#> $file2
#>   y
#> 1 a
#> 2 b

... বা ল্যাম্বদা ফাংশনটির মাধ্যমে অতিরিক্ত যুক্তিগুলি পাস করুন।

path_csv %>% 
  list_any(readr::read_csv, skip = 1)
#> Parsed with column specification:
#> cols(
#>   `1` = col_double()
#> )
#> Parsed with column specification:
#> cols(
#>   a = col_character()
#> )
#> $file1
#> # A tibble: 1 x 1
#>     `1`
#>   <dbl>
#> 1     2
#> 
#> $file2
#> # A tibble: 1 x 1
#>   a    
#>   <chr>
#> 1 b

path_csv %>% 
  list_any(~read.csv(., stringsAsFactors = FALSE)) %>% 
  map(as_tibble)
#> $file1
#> # A tibble: 2 x 1
#>       x
#>   <int>
#> 1     1
#> 2     2
#> 
#> $file2
#> # A tibble: 2 x 1
#>   y    
#>   <chr>
#> 1 a    
#> 2 b

1

অনুরোধ করা হয়েছিল আমি স্ট্যাকওভারফ্লো আর প্যাকেজে এই কার্যকারিতা যুক্ত করব। এটি একটি ক্ষুদ্র প্যাকেজ (এবং তৃতীয় পক্ষের প্যাকেজগুলির উপর নির্ভর করতে পারে না) দেওয়া হ'ল, আমি এখানে যা এলাম:

#' Bulk import data files 
#' 
#' Read in each file at a path and then unnest them. Defaults to csv format.
#' 
#' @param path        a character vector of full path names
#' @param pattern     an optional \link[=regex]{regular expression}. Only file names which match the regular expression will be returned.
#' @param reader      a function that can read data from a file name.
#' @param ...         optional arguments to pass to the reader function (eg \code{stringsAsFactors}).
#' @param reducer     a function to unnest the individual data files. Use I to retain the nested structure. 
#' @param recursive     logical. Should the listing recurse into directories?
#'  
#' @author Neal Fultz
#' @references \url{/programming/11433432/how-to-import-multiple-csv-files-at-once}
#' 
#' @importFrom utils read.csv
#' @export
read.directory <- function(path='.', pattern=NULL, reader=read.csv, ..., 
                           reducer=function(dfs) do.call(rbind.data.frame, dfs), recursive=FALSE) {
  files <- list.files(path, pattern, full.names = TRUE, recursive = recursive)

  reducer(lapply(files, reader, ...))
}

পাঠক এবং রিডিউসার ফাংশনকে প্যারামিটারাইজেশন করে, লোকেরা যদি তারা পছন্দ করে তবে ডেটা টেবিল বা ডিপ্লাইার ব্যবহার করতে পারে বা ছোট ডাটা সেটের জন্য উপযুক্ত বেস বেস ফাংশনগুলি ব্যবহার করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.