ডেটা.table বনাম dplyr: এক ভাল কিছু করতে পারেন না খারাপ না?




data.table (2)

সংক্ষিপ্ত বিবরণ

আমি dplyr . dplyr সঙ্গে অপেক্ষাকৃত পরিচিত, data.table সঙ্গে তাই না। আমি কিছু dplyr vignettes এবং উদাহরণ যে উপর SO পপ আপ করেছেন, এবং এতদূর আমার সিদ্ধান্ত যে মাধ্যমে পড়া আছে:

  1. data.table এবং dplyr গতিতে তুলনীয়, যখন অনেকগুলি (যেমন> 10-100K) গোষ্ঠী ছাড়া, এবং অন্য কোন পরিস্থিতিতে (নীচের benchmarks দেখুন)
  2. dplyr আরো অ্যাক্সেসযোগ্য সিনট্যাক্স আছে
  3. dplyr abstracts (বা হবে) সম্ভাব্য ডিবি মিথস্ক্রিয়া
  4. কিছু ক্ষুদ্র কার্যকারিতা পার্থক্য রয়েছে (নীচে "উদাহরণ / ব্যবহার" দেখুন)

আমার মনের মধ্যে 2. খুব ওজন বহন করে না কারণ আমি এটি data.table সাথে মোটামুটি পরিচিত, যদিও আমি বুঝতে পারি যে ব্যবহারকারীর জন্য নতুন উভয় ক্ষেত্রে এটি একটি বড় কারণ হবে। আমি আরও বেশি স্বজ্ঞাত বিষয়ে একটি যুক্তি এড়াতে চাই, কারণ এটি আমার data.table . data.table সম্পর্কে ইতিমধ্যে পরিচিত কোনও দৃষ্টিকোণ থেকে জিজ্ঞাসা করা নির্দিষ্ট প্রশ্নটির জন্য অপ্রাসঙ্গিক। "আরও স্বজ্ঞাত" দ্রুত বিশ্লেষণের দিকে পরিচালিত করে এমন একটি আলোচনা এড়াতে চাই (অবশ্যই সত্য, কিন্তু আবারও, এখানে আমি সবচেয়ে বেশি আগ্রহী নই)।

প্রশ্ন

আমি কি জানতে চাই:

  1. সেখানে বিশ্লেষণাত্মক কাজগুলি রয়েছে যা প্যাকেজগুলির সাথে পরিচিত ব্যক্তিদের জন্য এক বা অন্য প্যাকেজগুলির সাথে কোড করা অনেক সহজ (অর্থাত্ কীস্ট্রোকগুলির কিছু প্রয়োজনীয়তা বনাম প্রয়োজনীয় গোয়েন্দা স্তর, যেখানে প্রত্যেকেই একটি ভাল জিনিস)।
  2. অন্য একটি বনাম একটি প্যাকেজ মধ্যে কার্যকরীভাবে (2x চেয়ে বেশি) সঞ্চালিত হয় যে বিশ্লেষণাত্মক কাজ আছে।

সাম্প্রতিক এক সমঝোতা প্রশ্নটি আমাকে একটু বেশি ভাবতে dplyr , কারণ সেই বিন্দু পর্যন্ত আমি মনে করি না যে dplyr আমি ইতিমধ্যে data.table . data.table যা করতে পারি তার চেয়ে অনেক বেশি অফার data.table । এখানে dplyr সমাধান (প্রশ্ন শেষে তথ্য):

dat %.%
  group_by(name, job) %.%
  filter(job != "Boss" | year == min(year)) %.%
  mutate(cumu_job2 = cumsum(job2))

যা একটি data.table . data.table সমাধান আমার হ্যাক প্রচেষ্টা চেয়ে অনেক ভাল ছিল। যে বলেন, ভাল তথ্য data.table সমাধান খুব ভাল (ধন্যবাদ জিন-রবার্ট, অরুণ, এবং এখানে উল্লেখ্য আমি কঠোরভাবে সর্বাধিক সর্বোত্তম সমাধানের উপর একক বিবৃতির পক্ষে):

setDT(dat)[,
  .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], 
  by=list(id, job)
]

পরেরটির জন্য সিনট্যাক্স খুব স্পষ্ট বলে মনে হতে পারে, তবে আপনি যদি data.table (অর্থাত্ আরও কিছু গোপন কৌশল ব্যবহার করে না) ব্যবহার করেন তবে এটি বেশ সোজা।

আদর্শভাবে আমি যা দেখতে চাই তা হল কিছু ভাল উদাহরণ যা dplyr বা data.table উপায় উল্লেখযোগ্যভাবে dplyr বা যথেষ্ট ভালভাবে সম্পাদন করে।

উদাহরণ

ব্যবহার
  • dplyr গোষ্ঠীযুক্ত অপারেশনগুলিকে অনুমতি দেয় না যেগুলি ইচ্ছাকৃতভাবে সারির সংখ্যাগুলি ফেরত দেয় ( এডদিয়ের প্রশ্ন থেকে , দ্রষ্টব্য: এটি দেখে মনে হচ্ছে যে এটি dplayr 0.5 এও বাস্তবায়িত হবে, এছাড়াও @ বেগনিএনআর @ এডদিয়ের প্রশ্নের উত্তর দিয়ে একটি সম্ভাব্য কাজ-আশেপাশে কাজ করে) ।
  • data.table রোলিং যোগদান সমর্থন করে (ধন্যবাদ @ ডলস্টাসিয়াস) পাশাপাশি যোগদানের overlap
  • data.table অভ্যন্তরীণভাবে স্বয়ংক্রিয় DT[col %in% values] মাধ্যমে গতির জন্য DT[col == value] বা DT[col %in% values] data.table DT[col %in% values] DT[col == value] এক্সপ্রেশনগুলিকে সর্বোত্তম করে data.table যা একই বেস আর সিনট্যাক্স ব্যবহার করে বাইনারি অনুসন্ধান ব্যবহার করে। আরো কিছু বিস্তারিত এবং একটি ছোট বেঞ্চমার্ক জন্য এখানে দেখুন
  • dplyr ফাংশনগুলির মান মূল্যায়ন সংস্করণগুলি প্রদান করে (উদাহরণস্বরূপ dplyr , summarize_each_ ) যা dplyr এর প্রোগ্রাম্যাটিক ব্যবহার সহজ করতে পারে ( dplyr . dplyr প্রোগ্রাম্যাটিক ব্যবহার নিশ্চিতভাবে নিশ্চিত করা যায়, অবশ্যই কিছু সতর্কতা অবলম্বন, প্রতিস্থাপন / উদ্ধৃতি, ইত্যাদি আমার জ্ঞানে অন্তত প্রয়োজন )
benchmarks

উপাত্ত

এই প্রশ্ন বিভাগে দেখানো প্রথম উদাহরণের জন্য।

dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane", 
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob", 
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L, 
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L, 
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager", 
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager", 
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L, 
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id", 
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA, 
-16L))

প্রশ্ন শিরোনাম সরাসরি প্রতিক্রিয়া ...

dplyr স্পষ্টভাবে জিনিস যে তথ্য. data.table করতে পারে না।

আপনার পয়েন্ট # 3

dplyr abstracts (বা হবে) সম্ভাব্য ডিবি মিথস্ক্রিয়া

আপনার নিজের প্রশ্নের একটি সরাসরি উত্তর কিন্তু উচ্চ পর্যায়ে উচ্চতর হয় না। dplyrdata.tableএকটি একক এক্সটেনশান হিসাবে যেখানে একাধিক ডেটা স্টোরেজ Mechanisms সত্যিই একটি বর্ধিত সামনে শেষ হয় ।

dplyrএকই ব্যাকরণ ব্যবহার করে সমস্ত লক্ষ্যগুলির সাথে ব্যাক-এন্ড অ্যাগনস্টিক ইন্টারফেস হিসাবে দেখুন , যেখানে আপনি ইচ্ছাকৃতভাবে লক্ষ্যগুলি এবং হ্যান্ডলারগুলি প্রসারিত করতে পারেন। দৃষ্টিকোণ data.tableথেকে dplyr, যারা লক্ষ্য এক।

আপনি data.tableঅন-ডিস্ক বা নেটওয়ার্কযুক্ত ডেটা স্টোরগুলির সাথে কাজ করে এমন SQL স্টেটমেন্টগুলি তৈরি করতে আপনার প্রশ্নের অনুবাদ করার কোনও দিন দেখতে পাবেন না (আমি আশা করি) ।

dplyrসম্ভবত কাজ করতে পারে data.tableনা বা ভাল নাও করতে পারে।

মেমরি কাজ নকশা উপর ভিত্তি করে data.table, প্রশ্ন তুলনায় সমান্তরাল প্রক্রিয়াকরণের মধ্যে নিজেকে প্রসারিত একটি আরো কঠিন সময় থাকতে পারে dplyr

ইন-শরীরের প্রশ্নের প্রতিক্রিয়া ...

ব্যবহার

সেখানে বিশ্লেষণাত্মক কাজগুলি রয়েছে যা প্যাকেজগুলির সাথে পরিচিত ব্যক্তিদের জন্য এক বা অন্য প্যাকেজগুলির সাথে কোড করা অনেক সহজ (অর্থাত্ কীস্ট্রোকগুলির কিছু প্রয়োজনীয়তা বনাম প্রয়োজনীয় গোয়েন্দা স্তর, যেখানে প্রত্যেকেই একটি ভাল জিনিস)।

এটি একটি প্যান্ট মত মনে হতে পারে কিন্তু প্রকৃত উত্তর নেই। সরঞ্জামগুলির সাথে পরিচিত ব্যক্তিরা মনে করেন যে তাদের কাছে সবচেয়ে বেশি পরিচিত একজন বা সেই হাতের কাজটি আসলেই সঠিক। যে বলে, কখনও কখনও আপনি একটি নির্দিষ্ট পঠনযোগ্যতা, কখনও কখনও কর্মক্ষমতা একটি স্তর উপস্থাপন করতে চান, এবং যখন আপনি উভয় উচ্চ পর্যায়ে পর্যাপ্ত প্রয়োজন আছে, আপনি কি পরিষ্কার এক্সট্রাকশন আছে ইতিমধ্যে বরাবর যেতে অন্য সরঞ্জাম প্রয়োজন হতে পারে ।

কর্মক্ষমতা

অন্য একটি বনাম একটি প্যাকেজ মধ্যে কার্যকরীভাবে (2x চেয়ে বেশি) সঞ্চালিত হয় যে বিশ্লেষণাত্মক কাজ আছে।

আবার, না। অন্তর্নিহিত তথ্য দোকান এবং নিবন্ধিত হ্যান্ডলার কিছু ক্ষেত্রে সীমাবদ্ধ হচ্ছে বোঝা যেখানে এটি পায় যেখানে data.tableসবকিছু দক্ষ হচ্ছে excels ।dplyr

এর মানে হল যখন আপনি একটি কার্যকারিতা সমস্যার সাথে মধ্যে চালানো data.tableআপনি নিশ্চিত এটা আপনার প্রশ্নের ফাংশন আছে এবং যদি এটা হতে পারে হয় আসলে সঙ্গে একটি বোতলের data.tableতারপর আপনি নিজেকে একটি প্রতিবেদন দাখিল আনন্দ জিতেছ। ব্যাক-এন্ড dplyrব্যবহার করার সময় এটিও সত্য data.table। আপনি কিছু overhead দেখতে পারেন কিন্তু বিজোড় আপনার প্রশ্নের হয়।dplyr

যখন dplyrব্যাক-এন্ডগুলির সাথে পারফরম্যান্সের সমস্যা থাকে তখন আপনি হাইব্রিড মূল্যায়নের জন্য একটি ফাংশন নিবন্ধন করে বা (ডেটাবেসের ক্ষেত্রে) নির্বাহের পূর্বে জেনারেট হওয়া প্রশ্নের সাথে ম্যানিপুলেশন করে তাদের চারপাশে পেতে পারেন।

এছাড়াও ডেটা.table চেয়ে plyr ভাল যখন গ্রহণযোগ্য উত্তর দেখুন ?


একটি সর্বশ্রেষ্ঠ উত্তর / তুলনা (গুরুত্বের কোন বিশেষ ক্রম অনুসারে) প্রদান করার জন্য আমাদের অন্তত এই দিকগুলি আবরণ করতে হবে: Speed , Memory usage , Syntax এবং Features

আমার লক্ষ্যটি ডেটা.table দৃষ্টিকোণ থেকে যতটা সম্ভব পরিষ্কারভাবে এই প্রতিটি আবরণ করা হয়।

দ্রষ্টব্য: অন্যথায় স্পষ্টভাবে উল্লিখিত না হওয়া পর্যন্ত, dplr এর উল্লেখ করে, আমরা DPLER এর ডেটা.ফ্রেম ইন্টারফেসটি উল্লেখ করি যার ইন্টারনালগুলি Rcpp ব্যবহার করে C ++ এ রয়েছে।

ডেটা.table সিনট্যাক্স তার ফর্মের সাথে সামঞ্জস্যপূর্ণ - DT[i, j, by]i রাখা, j এবং একসঙ্গে নকশা দ্বারা হয়। একসঙ্গে সম্পর্কিত অপারেশনগুলি পালন করে, এটি গতি এবং আরও গুরুত্বপূর্ণভাবে মেমরি ব্যবহারের জন্য অপারেশনগুলি সহজে অপ্টিমাইজ করার মঞ্জুরি দেয় এবং সিনট্যাক্সের সামঞ্জস্য বজায় রাখার সময় কিছু শক্তিশালী বৈশিষ্ট্য সরবরাহ করে

1. গতি

বেশ কয়েকটি মানচিত্র (বেশিরভাগ ক্ষেত্রে গোষ্ঠী ক্রিয়াকলাপের উপর) ইতিমধ্যেই প্রশ্ন করা হয়েছে যে ডেটা.table ডায়ালারের চেয়ে দ্রুততর হয় এবং সংখ্যা বৃদ্ধি করে গোষ্ঠীগুলির সংখ্যা এবং / অথবা সারির সংখ্যা বৃদ্ধি করে, যার মধ্যে ম্যাট দ্বারা 10 মিলিয়ন 100 বিলিয়ন সারিতে ( 100 গিগাবাইট RAM) 100 মিলিয়ন গোষ্ঠী এবং বিভিন্ন গ্রুপিং কলাম যা pandas সাথে তুলনা করে। এছাড়াও আপডেট benchmarks দেখুন , যা Spark এবং pydatatable হিসাবে ভাল অন্তর্ভুক্ত।

বেঞ্চমার্কগুলিতে, এই অবশিষ্ট দিকগুলির পাশাপাশি এটি ভাল হবে:

  • সারির একটি উপসেট জড়িত গোষ্ঠী ক্রিয়াকলাপ - অর্থাৎ, DT[x > val, sum(y), by = z] টাইপ অপারেশন।

  • আপডেট এবং যোগদান হিসাবে অন্যান্য অপারেশন Benchmark।

  • এছাড়াও রানটাইম ছাড়া প্রতিটি অপারেশন জন্য বেঞ্চমার্ক মেমরি পদচিহ্ন

2. মেমরি ব্যবহার

  1. filter() বা slice() dplayr মধ্যে অপারেশন অন্তর্ভুক্ত মেমরি অযোগ্য (তথ্য.ফ্রেমস এবং data.tables উভয়) হতে পারে। এই পোস্টটি দেখুন ।

    মনে রাখবেন যে হেডলি এর মন্তব্যটি গতির বিষয়ে আলোচনা করে (যেটি তার জন্য খুব দ্রুত হয়), তবে এখানে প্রধান উদ্বেগ স্মৃতি

  2. এই মুহূর্তে data.table ইন্টারফেসটি কাউকে রেফারেন্স দ্বারা কলাম পরিবর্তন / হালনাগাদ করতে দেয় (নোট করুন যে আমরা ফলাফলটিকে একটি পরিবর্তনশীলকে পুনরায় বরাদ্দ করতে হবে না)।

    # sub-assign by reference, updates 'y' in-place
    DT[x >= 1L, y := NA]

    কিন্তু dplyr রেফারেন্স দ্বারা আপডেট হবে না । Dplr সমতুল্য হবে (নোট ফলাফল পুনরায় বরাদ্দ করা প্রয়োজন মনে রাখবেন):

    # copies the entire 'y' column
    ans <- DF %>% mutate(y = replace(y, which(x >= 1L), NA))

    এই জন্য একটি উদ্বেগের উল্লেখযোগ্য স্বচ্ছতা । রেফারেন্স দ্বারা একটি তথ্য.table বস্তু আপডেট করা, বিশেষত একটি ফাংশন মধ্যে সবসময় সবসময় পছন্দসই হতে পারে না। কিন্তু এটি একটি অবিশ্বাস্যভাবে দরকারী বৈশিষ্ট্য: আকর্ষণীয় ক্ষেত্রে this এবং this পোস্ট দেখুন। এবং আমরা এটা রাখতে চাই।

    অতএব আমরা ডেটা.table তে shallow() ফাংশন রপ্তানি করার জন্য কাজ করছি যা ব্যবহারকারীকে উভয় সম্ভাবনার সাথে সরবরাহ করবে। উদাহরণস্বরূপ, যদি কোনও ফাংশনের মধ্যে ইনপুট ডেটা.table সংশোধন করা না যায় তবে এটি করতে পারেন:

    foo <- function(DT) {
        DT = shallow(DT)          ## shallow copy DT
        DT[, newcol := 1L]        ## does not affect the original DT 
        DT[x > 2L, newcol := 2L]  ## no need to copy (internally), as this column exists only in shallow copied DT
        DT[x > 2L, x := 3L]       ## have to copy (like base R / dplyr does always); otherwise original DT will 
                                  ## also get modified.
    }

    shallow() ব্যবহার করে না shallow() , পুরানো কার্যকারিতা বজায় রাখা হয়:

    bar <- function(DT) {
        DT[, newcol := 1L]        ## old behaviour, original DT gets updated by reference
        DT[x > 2L, x := 3L]       ## old behaviour, update column x in original DT.
    }

    shallow() ব্যবহার করে একটি অগভীর অনুলিপি তৈরি করে, আমরা বুঝি যে আপনি মূল বস্তুটি সংশোধন করতে চান না। কলামগুলির অনুলিপি নিশ্চিত করার জন্য আমরা অভ্যন্তরীণভাবে সবকিছু যত্ন নেব যখন আপনি একেবারে প্রয়োজনে শুধুমাত্র সংশোধন করবেন। বাস্তবায়িত হলে, উভয় possibilties সঙ্গে ব্যবহারকারী প্রদান করার সময় এটি একযোগে স্বচ্ছ স্বচ্ছতা সমস্যা নিষ্পত্তি করা উচিত।

    এছাড়াও, একবার shallow() এক্সপোর্ট করা হয় dplayr এর ডেটা.table ইন্টারফেসটি প্রায় সমস্ত কপি এড়ানো উচিত। তাই যারা ডাইলারের সিনট্যাক্স পছন্দ করে তারা এটি ডেটা.tables দিয়ে ব্যবহার করতে পারে।

    তবে তথ্যে ডেটা.table প্রদান করে এমন অনেক বৈশিষ্ট্য অভাব থাকবে, সহ (উপ) - রেফারেন্স দ্বারা সাইন ইনমেন্ট।

  3. যোগদান করার সময় সমষ্টিগত:

    ধরুন আপনার দুটি ডেটা.tables আছে নিম্নরূপ:

    DT1 = data.table(x=c(1,1,1,1,2,2,2,2), y=c("a", "a", "b", "b"), z=1:8, key=c("x", "y"))
    #    x y z
    # 1: 1 a 1
    # 2: 1 a 2
    # 3: 1 b 3
    # 4: 1 b 4
    # 5: 2 a 5
    # 6: 2 a 6
    # 7: 2 b 7
    # 8: 2 b 8
    DT2 = data.table(x=1:2, y=c("a", "b"), mul=4:3, key=c("x", "y"))
    #    x y mul
    # 1: 1 a   4
    # 2: 2 b   3

    এবং কলাম x,y দ্বারা যোগদান করার সময় আপনি DT2 প্রতিটি সারির জন্য sum(z) * mul পেতে চাইবেন। আমরা হয়:

    • 1) সমষ্টিগত DT1 1 পেতে sum(z) , 2) একটি যোগদান সঞ্চালন করুন এবং 3) গুণমান (বা)

      # data.table way
      DT1[, .(z = sum(z)), keyby = .(x,y)][DT2][, z := z*mul][]
      
      # dplyr equivalent
      DF1 %>% group_by(x, y) %>% summarise(z = sum(z)) %>% 
          right_join(DF2) %>% mutate(z = z * mul)
    • 2) by = .EACHI এটি সব করুন ( by = .EACHI বৈশিষ্ট্য ব্যবহার by = .EACHI ):

      DT1[DT2, list(z=sum(z) * mul), by = .EACHI]

    সুবিধা কি?

    • আমাদের মধ্যবর্তী ফলাফলের জন্য মেমরি বরাদ্দ করতে হবে না।

    • আমাদের দুবার গ্রুপ / হ্যাশ করতে হবে না (একত্রিতকরণের জন্য এবং যোগদানের জন্য অন্য)।

    • এবং আরো গুরুত্বপূর্ণ, আমরা অপারেশন করতে চেয়েছিলেন অপারেশন j (2) এ খুঁজছেন দ্বারা স্পষ্ট।

    by = .EACHI বিস্তারিত বিবরণের জন্য এই পোস্টটি দেখুন। কোন মধ্যবর্তী ফলাফল materialized হয়, এবং যোগদান + সমষ্টি এক যেতে সব সঞ্চালিত হয়।

    this , বাস্তব ব্যবহারের পরিস্থিতিতে জন্য this এবং this পোস্ট।

    dplyr আপনি মেমরি পরিপ্রেক্ষিতে (যা পরিবর্তে গতিতে অনুবাদ) মধ্যে যোগদান এবং সমষ্টিগত বা একত্রিত করা হবে এবং তারপর যোগদান , যা দক্ষ হিসাবে নয়, যোগদান করতে হবে।

  4. আপডেট এবং যোগদান:

    নিচে দেখানো ডেটা.table কোড বিবেচনা করুন:

    DT1[DT2, col := i.mul]

    DT1 এর কলাম col যোগ করে / আপডেট করে DT2 থেকে DT2 থেকে যেখানে DT2 এর কী কলাম DT1 মেলে। আমি এই অপারেশনটির সঠিকভাবে সমানভাবে বলতে পারি না, অর্থাৎ, *_join অপারেশন এড়ানো ছাড়া, dplyr একটি নতুন কলাম যোগ করার জন্য পুরো DT1 অনুলিপি করতে হবে, যা অপ্রয়োজনীয়।

    একটি বাস্তব ব্যবহারের দৃশ্যকল্প জন্য এই পোস্টটি পরীক্ষা করে দেখুন।

সংক্ষেপে বোঝা যায় যে প্রতিটি অপ্টিমাইজেশান বিষয়ে কিছুটা গুরুত্বপূর্ণ। গ্রেস হুপার বলবেন, আপনার ন্যানোসেকেন্ড মনে করুন !

3. সিনট্যাক্স

এর এখন সিনট্যাক্স তাকান। হ্যাডলি here মন্তব্য করেছেন:

ডেটা টেবিল অত্যন্ত দ্রুত হয় তবে আমি মনে করি তাদের সংক্ষিপ্তসারটি শেখা কঠিন এবং এটি যে কোডটি ব্যবহার করে আপনি এটি লেখার পরে পড়তে কঠিন

আমি এই বক্তব্য নিরর্থক কারণ এটি খুব বিষয়ী। আমরা সম্ভবত চেষ্টা করতে পারেন সিনট্যাক্স মধ্যে ধারাবাহিকতা বিপরীতে। আমরা data.table এবং dplayr সিনট্যাক্স পাশাপাশি পাশাপাশি তুলনা করা হবে।

আমরা নীচে দেখানো ডামি তথ্য দিয়ে কাজ করবে:

DT = data.table(x=1:10, y=11:20, z=rep(1:2, each=5))
DF = as.data.frame(DT)
  1. বেসিক একীকরণ / আপডেট অপারেশন।

    # case (a)
    DT[, sum(y), by = z]                       ## data.table syntax
    DF %>% group_by(z) %>% summarise(sum(y)) ## dplyr syntax
    DT[, y := cumsum(y), by = z]
    ans <- DF %>% group_by(z) %>% mutate(y = cumsum(y))
    
    # case (b)
    DT[x > 2, sum(y), by = z]
    DF %>% filter(x>2) %>% group_by(z) %>% summarise(sum(y))
    DT[x > 2, y := cumsum(y), by = z]
    ans <- DF %>% group_by(z) %>% mutate(y = replace(y, which(x > 2), cumsum(y)))
    
    # case (c)
    DT[, if(any(x > 5L)) y[1L]-y[2L] else y[2L], by = z]
    DF %>% group_by(z) %>% summarise(if (any(x > 5L)) y[1L] - y[2L] else y[2L])
    DT[, if(any(x > 5L)) y[1L] - y[2L], by = z]
    DF %>% group_by(z) %>% filter(any(x > 5L)) %>% summarise(y[1L] - y[2L])
    • data.table সিনট্যাক্স কম্প্যাক্ট এবং dplyr এর বেশ verbose হয়। বিষয়গুলি (ক) ক্ষেত্রে কম বা সমান সমতুল্য।

    • ক্ষেত্রে (খ), সংক্ষেপে যখন আমরা dplr মধ্যে filter() ব্যবহার করতে হবে। কিন্তু আপডেট করার সময়, আমরা mutate() মধ্যে যুক্তি সরানো ছিল। ডেটা.table- তে, আমরা একই লজিকের সাথে উভয় ক্রিয়াকলাপ প্রকাশ করি - x > 2 যেখানে সারিগুলিতে কাজ করে, কিন্তু প্রথম ক্ষেত্রে, sum(y) পেতে হবে, তবে দ্বিতীয় ক্ষেত্রে তার ক্রম সংখ্যার সাথে y জন্য সারিগুলি আপডেট করুন।

      আমরা যখন DT[i, j, by] ফর্মটি সামঞ্জস্যপূর্ণ বলি তখন আমরা এটি বলতে চাই।

    • একইভাবে ক্ষেত্রে (গ), if-else শর্ত থাকে, তবে আমরা তথ্য - উপাত্ত এবং dplr উভয় ক্ষেত্রে " যেমন- হয়" যুক্তিটি প্রকাশ করতে সক্ষম। যাইহোক, যদি আমরা কেবল সেই সারিগুলি ফেরত দিতে চাই যেখানে শর্তটি সন্তুষ্ট করে এবং অন্যথায় এড়িয়ে যায়, আমরা summarise() ব্যবহার করতে পারি না (AFAICT)। আমাদের প্রথমে filter() এবং প্রথমে সংক্ষিপ্ত করতে হবে কারণ summarise() সর্বদা একটি একক মান আশা করে।

      এটি একই ফলাফল প্রদান করে, filter() ব্যবহার করে এখানে প্রকৃত ক্রিয়াকলাপটি কম সুস্পষ্ট করে তোলে।

      প্রথম ক্ষেত্রে এটি filter() ব্যবহার করা খুব ভাল হতে পারে (আমার কাছে স্পষ্ট মনে হচ্ছে না), কিন্তু আমার পয়েন্টটি আমাদের উচিত নয়।

  2. একাধিক কলাম উপর একীকরণ / আপডেট

    # case (a)
    DT[, lapply(.SD, sum), by = z]                     ## data.table syntax
    DF %>% group_by(z) %>% summarise_each(funs(sum)) ## dplyr syntax
    DT[, (cols) := lapply(.SD, sum), by = z]
    ans <- DF %>% group_by(z) %>% mutate_each(funs(sum))
    
    # case (b)
    DT[, c(lapply(.SD, sum), lapply(.SD, mean)), by = z]
    DF %>% group_by(z) %>% summarise_each(funs(sum, mean))
    
    # case (c)
    DT[, c(.N, lapply(.SD, sum)), by = z]     
    DF %>% group_by(z) %>% summarise_each(funs(n(), mean))
    • ক্ষেত্রে (ক) কোডগুলি সমান সমান। তথ্য.table পরিচিত বেস ফাংশন lapply() , যখন dplyr ফাংশন একটি গুচ্ছ funs() সঙ্গে *_each() funs()

    • data.table এর := কলামের নাম সরবরাহ করতে হবে, যখন dplyr স্বয়ংক্রিয়ভাবে এটি তৈরি করে।

    • ক্ষেত্রে (খ), dplyr এর সিনট্যাক্স তুলনামূলকভাবে সহজবোধ্য। একাধিক ফাংশন উপর সমষ্টি / আপডেট উন্নতি ডেটা.table এর তালিকা।

    • ক্ষেত্রে (c) যাইহোক, dplr শুধুমাত্র একবার পরিবর্তে n() অনেকগুলি কলামের পরিবর্তে ফিরে আসবে। Data.table এ, আমাদের যা করতে হবে তা হলো j একটি তালিকা ফেরত দিতে। তালিকা প্রতিটি উপাদান ফলে একটি কলাম হয়ে যাবে। সুতরাং, আমরা আবার, পরিচিত বেস ফাংশন c() সংযোজন করতে ব্যবহার করতে পারি। একটি list যা একটি list

    দ্রষ্টব্য: আবার, ডেটা.table, আমাদের যা করতে হবে তা হল j একটি তালিকা ফেরত পাঠানো। তালিকা প্রতিটি উপাদান ফলে কলাম হয়ে যাবে। আপনি c() , as.list() , lapply() , list() ইত্যাদি ... কোনও নতুন ফাংশন শিখতে না lapply() এটি সম্পূর্ণ করতে বেস ফাংশন ব্যবহার করতে পারেন।

    আপনাকে শুধুমাত্র বিশেষ ভেরিয়েবলগুলি শিখতে হবে - ন্যূনতম এবং। .SD । Dplr মধ্যে সমতুল্য n() এবং .

  3. যোগদান করেছে

    dplayr প্রতিটি ধরনের যোগদানের জন্য পৃথক ফাংশন সরবরাহ করে যেখানে ডেটা.table একই সিনট্যাক্স DT[i, j, by] (এবং কারনে) ব্যবহার করে যোগদান করতে দেয়। এটি একটি বিকল্প হিসাবে সমতুল্য merge.data.table() ফাংশন সরবরাহ করে।

    setkey(DT1, x, y)
    
    # 1. normal join
    DT1[DT2]            ## data.table syntax
    left_join(DT2, DT1) ## dplyr syntax
    
    # 2. select columns while join    
    DT1[DT2, .(z, i.mul)]
    left_join(select(DT2, x, y, mul), select(DT1, x, y, z))
    
    # 3. aggregate while join
    DT1[DT2, .(sum(z) * i.mul), by = .EACHI]
    DF1 %>% group_by(x, y) %>% summarise(z = sum(z)) %>% 
        inner_join(DF2) %>% mutate(z = z*mul) %>% select(-mul)
    
    # 4. update while join
    DT1[DT2, z := cumsum(z) * i.mul, by = .EACHI]
    ??
    
    # 5. rolling join
    DT1[DT2, roll = -Inf]
    ??
    
    # 6. other arguments to control output
    DT1[DT2, mult = "first"]
    ??
    • কেউ কেউ প্রতিটি নিকার (বাম, ডান, অভ্যন্তরীণ, বিরোধী, আধা ইত্যাদি) যোগ করার জন্য একটি পৃথক ফাংশন খুঁজে পেতে পারে, অন্যরা ডেটা.table এর DT[i, j, by] , বা merge() যা বেসের মতো আর

    • তবে dplyr শুধু যে যোগদান যোগদান। বেশি না. কিছুই কম.

    • data.tables যোগদান করার সময় কলাম নির্বাচন করতে পারেন (2), এবং dplr তে আপনাকে প্রথমে উপরে দেখানোর জন্য আগে data.frames উভয়তে select() প্রথমে select() করতে হবে। অন্যথায় আপনি কেবলমাত্র তাদের অপসারণ করতে অপ্রয়োজনীয় কলামগুলির সাথে যোগসূত্রটি উপাদেয় করবেন এবং এটি কার্যকর নয়।

    • (3) যোগদান করার সময় data.tables একত্রিত হতে পারে এবং (4) যোগদান করার সময় আপডেট , by = .EACHI বৈশিষ্ট্য ব্যবহার by = .EACHI । কেন পুরো যোগদান উপাদান যোগ মাত্র কয়েক কলাম যোগ / আপডেট?

    • data.table যোগদান ঘূর্ণায়মান সক্ষম (5) - রোল ফরোয়ার্ড, LOCF , রোল পিছনে, এনওসিবি , nearest ।

    • তথ্য.table এছাড়াও mult = যুক্তি যা প্রথম , শেষ বা সব মিল নির্বাচন করে (6)।

    • data.table অনুমতি আছে। allow.cartesian = TRUE ভুল যোগদানের থেকে রক্ষা করার জন্য allow.cartesian = TRUE যুক্তি।

আবার, সিনট্যাক্সটি DT[i, j, by] সাথে সামঞ্জস্যপূর্ণ DT[i, j, by] অতিরিক্ত আর্গুমেন্টগুলি আউটপুটকে আরও নিয়ন্ত্রণ করার অনুমতি দেয়।

  1. do() ...

    dplyr এর সারসংক্ষেপ বিশেষভাবে একটি একক মান ফেরত যে ফাংশন জন্য ডিজাইন করা হয়। যদি আপনার ফাংশন একাধিক / অসাম্য মানের ফেরত দেয়, তবে আপনাকে do() করতে রিসোর্ট করতে do() । আপনি আপনার সমস্ত ফাংশন ফিরে মান সম্পর্কে পূর্বেই জানতে হবে।

    DT[, list(x[1], y[1]), by = z]                 ## data.table syntax
    DF %>% group_by(z) %>% summarise(x[1], y[1]) ## dplyr syntax
    DT[, list(x[1:2], y[1]), by = z]
    DF %>% group_by(z) %>% do(data.frame(.$x[1:2], .$y[1]))
    
    DT[, quantile(x, 0.25), by = z]
    DF %>% group_by(z) %>% summarise(quantile(x, 0.25))
    DT[, quantile(x, c(0.25, 0.75)), by = z]
    DF %>% group_by(z) %>% do(data.frame(quantile(.$x, c(0.25, 0.75))))
    
    DT[, as.list(summary(x)), by = z]
    DF %>% group_by(z) %>% do(data.frame(as.list(summary(.$x))))
    • .SD এর সমতুল্য .

    • ডেটা.table এ, আপনি জেতে বেশ কিছু কিছু নিক্ষেপ করতে পারেন - মনে রাখা একমাত্র জিনিস এটি একটি তালিকা ফেরত পাঠানো যাতে তালিকার প্রতিটি উপাদান কলামে রূপান্তরিত হয়।

    • Dplyr, যে করতে পারেন না। আপনার ফাংশন সর্বদা একটি একক মান ফেরত হবে কিনা তা হিসাবে আপনি নিশ্চিত কিভাবে উপর নির্ভর করে do() করতে resorted আছে। এবং এটা বেশ ধীর।

আবার, ডেটা.table এর সিনট্যাক্স DT[i, j, by] সাথে সামঞ্জস্যপূর্ণ। আমরা শুধু এই জিনিস সম্পর্কে চিন্তা ছাড়া j মধ্যে এক্সপ্রেশন নিক্ষেপ রাখা যাবে।

এই SO প্রশ্ন এবং এই এক নজরে আছে । আমি ডাইলার এর সিনট্যাক্স ব্যবহার করে সহজভাবে উত্তর প্রকাশ করা সম্ভব হবে যদি ভাবছি ...

সংক্ষেপে, আমি বিশেষ করে ডায়ালারের সিনট্যাক্সটি অপ্রাসঙ্গিক, সীমিত বা অপারেশনগুলি সহজতর করতে ব্যর্থ হয় এমন কয়েকটি উদাহরণকে হাইলাইট করেছি। এটি বিশেষভাবে কারণ ডেটা.table বেশিরভাগ ব্যাকল্যাশ "কঠিন পড়তে / শিখতে" সিনট্যাক্স (যেমন আটকানো / উপরের লিঙ্কযুক্ত) এর সাথে পায়। সবচেয়ে সহজবোধ্য অপারেশন সম্পর্কে dplyr আলাপ আবরণ যে বেশিরভাগ পোস্ট। এবং যে মহান। তবে এটির সিনট্যাক্স এবং বৈশিষ্ট্য সীমাবদ্ধতাগুলি উপলব্ধি করাও গুরুত্বপূর্ণ, এবং আমি এখনও এটির একটি পোস্ট দেখতে পাচ্ছি না।

data.table পাশাপাশি তার quirks আছে (যা আমি নির্দিষ্ট করেছি যে আমরা ঠিক করার চেষ্টা করছেন)। আমরা ডেটা.table এর যোগদান উন্নত করার চেষ্টা করছি যেমন আমি here হাইলাইট করেছি।

তবে ডেটা.table এর তুলনায় ডাইলারের অভাবের বৈশিষ্ট্যগুলি বিবেচনা করা উচিত।

4. বৈশিষ্ট্য

আমি এখানে এবং এছাড়াও এই পোস্টে অধিকাংশ বৈশিষ্ট্য নির্দেশ করেছেন। এছাড়াও:

  • ফ્રેડ - দ্রুত ফাইল পাঠক এখন একটি দীর্ঘ সময়ের জন্য উপলব্ধ করা হয়েছে।

  • fwrite - একটি সমান্তরাল দ্রুত ফাইল লেখক এখন উপলব্ধ। আরো উন্নয়ন সম্পর্কে ট্র্যাক রাখার জন্য বাস্তবায়ন এবং #1664 বিস্তারিত ব্যাখ্যা করার জন্য এই পোস্টটি দেখুন।

  • স্বয়ংক্রিয় সূচী - অভ্যন্তরীণভাবে ভিত্তি হিসাবে বেস আর সিনট্যাক্স অপ্টিমাইজ করার জন্য আরেকটি সহজ বৈশিষ্ট্য।

  • অ্যাড-হক গ্রুপিং : dplyr summarise() , যা সবসময় পছন্দসই নাও হতে পারে ভেরিয়েবল গোষ্ঠী দ্বারা ফলাফল প্রকার করে।

  • ডেটা.table অনেকগুলি সুবিধা যোগ করে (উপরে গতি / মেমরি দক্ষতা এবং সিনট্যাক্সের জন্য) যোগ করা হয়েছে।

  • অ-ইইউ যোগদান করে : অন্যান্য অপারেটরগুলির সাথে <=, <, >, >= ডেটা.table যোগের অন্যান্য সুবিধাগুলি সহ যোগদান করার অনুমতি দেয়।

  • ওভারল্যাপিং পরিসীমা যোগদান সম্প্রতি data.table প্রয়োগ করা হয়েছে। Benchmarks সঙ্গে একটি ওভারভিউ জন্য এই পোস্টটি পরীক্ষা করে দেখুন।

  • setorder() ফাংশন দ্বারা তথ্য.tables সত্যিই দ্রুত reordering যে তথ্য.table মধ্যে ফাংশন।

  • dplayr একই সিনট্যাক্স ব্যবহার করে ডাটাবেস ইন্টারফেস উপলব্ধ, যা তথ্য.table মুহূর্তে না।

  • data.table সেট অপারেশনগুলির আরও দ্রুত সমতুল্য (Jan fsetdiff দ্বারা লিখিত) প্রদান করে - fsetdiff , fintersect , funion এবং fsetequal অতিরিক্ত all যুক্তি (যেমন SQL তে)।

  • কোনও মাস্কিং সতর্কবার্তা ছাড়াই ডেটা.table লোডগুলি লোড করে এবং কোনও R প্যাকেজে পাস করার সময় [.data.frame সঙ্গতিপূর্ণতার জন্য here বর্ণিত একটি প্রক্রিয়া রয়েছে। dplayr বেস ফাংশন filter পরিবর্তন, lag এবং [ যা সমস্যা হতে পারে; যেমন here এবং here ।

অবশেষে:

  • ডেটাবেসে - ডেটা.table একই ইন্টারফেস সরবরাহ করতে পারে এমন কোনও কারণ নেই, তবে এটি এখন অগ্রাধিকার নয়। ব্যবহারকারীরা যদি সেই বৈশিষ্ট্যটি পছন্দ করে তবে এটি হয়ত ফুটে উঠতে পারে .. নিশ্চিত না।

  • সমান্তরালতা - কেউ এগিয়ে যায় এবং এটি না হওয়া পর্যন্ত সবকিছু কঠিন। অবশ্যই এটি চেষ্টা করবে (থ্রেড নিরাপদ হচ্ছে)।

    • OpenMP ব্যবহার করে ক্রমবর্ধমান কর্মক্ষমতা লাভের জন্য পরিচিত সময়সীমার অংশ সমান্তরাল করার দিকে বর্তমানে অগ্রগতি করা হচ্ছে (v1.9.7 devel)।




dplyr