ডাটা.ট্যাবেলে রেফারেন্স দিয়ে একটি সারি কীভাবে মুছবেন?


150

আমার প্রশ্নে অনুলিপি বনাম রেফারেন্স দ্বারা নিয়োগ সঙ্গে সম্পর্কযুক্ত data.table। আমি জানতে চাইছি কেউ রেফারেন্স অনুসারে সারিগুলি মুছে ফেলতে পারে কিনা

DT[ , someCol := NULL]

আমি জানতে চাই

DT[someRow := NULL, ]

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

DT = data.table(x = rep(c("a", "b", "c"), each = 3), y = c(1, 3, 6), v = 1:9)
#      x y v
# [1,] a 1 1
# [2,] a 3 2
# [3,] a 6 3
# [4,] b 1 4
# [5,] b 3 5
# [6,] b 6 6
# [7,] c 1 7
# [8,] c 3 8
# [9,] c 6 9

বলুন আমি এই ডেটা থেকে প্রথম সারিটি মুছতে চাই। টেবিল। আমি জানি আমি এটি করতে পারি:

DT <- DT[-1, ]

কিন্তু প্রায়ই আমরা, যে এড়াতে চান কারণ আমরা অবজেক্ট কপি করা হয় (এবং যদি এন যে, 3 * এন পুনরুদ্ধার সম্পর্কে প্রয়োজন object.size(DT), এখানে নির্দিষ্ট এখন আমি খুঁজে পাওয়া যায়নি। set(DT, i, j, value)আমি জানি (যেমন এখানে সেট নির্দিষ্ট মান। সব সেট সারি 1 এবং 2 এবং কলাম 2 এবং 3 থেকে শূন্যের মানগুলি)

set(DT, 1:2, 2:3, 0) 
DT
#      x y v
# [1,] a 0 0
# [2,] a 0 0
# [3,] a 6 3
# [4,] b 1 4
# [5,] b 3 5
# [6,] b 6 6
# [7,] c 1 7
# [8,] c 3 8
# [9,] c 6 9

তবে কীভাবে আমি প্রথম দুটি সারি মুছব, বলুন? এরকম

set(DT, 1:2, 1:3, NULL)

পুরো ডিটি কে নুল করে দেয়।

আমার এসকিউএল জ্ঞানটি খুব সীমাবদ্ধ, সুতরাং আপনারা আমাকে বলুন: প্রদত্ত ডেটা টেবিলটি এসকিউএল প্রযুক্তি ব্যবহার করে, সেখানে কি এসকিউএল কমান্ডের সমতুল্য?

DELETE FROM table_name
WHERE some_column=some_value

ডেটা.ট্যাবেলে?


17
আমি মনে করি না যে এটি data.table()এসকিউএল প্রযুক্তিটি এত বেশি ব্যবহার করে যে কোনও এসকিউএল-এর বিভিন্ন ক্রিয়াকলাপ এবং এ-তে বিভিন্ন যুক্তির মধ্যে একটি সমান্তরাল আঁকতে পারে data.table। আমার কাছে, "প্রযুক্তি" এর উল্লেখটি কিছুটা বোঝায় যে data.tableএসকিউএল ডাটাবেসের শীর্ষে বসে আছে কোথাও, যা আফাইক নয়।
চেজ

1
ধন্যবাদ তাড়া। হ্যাঁ, আমি অনুমান করি যে এসকিএল উপমাটি একটি বুনো অনুমান ছিল।
ফ্লোরিয়ান ওসওয়াল্ড

1
প্রায়শই এটি সারি রাখার জন্য একটি পতাকা সংজ্ঞায়িত করার জন্য পর্যাপ্ত হওয়া উচিত, যেমন DT[ , keep := .I > 1]পরবর্তীকালের ক্রিয়াকলাপগুলির জন্য সাবসেট: DT[(keep), ...]সম্ভবত setindex(DT, keep)এই সাবসেটিংয়ের গতিও। পেনেসিয়া নয়, তবে আপনার ওয়ার্কফ্লোতে ডিজাইনের পছন্দ হিসাবে বিবেচনা করা সার্থক - আপনি কি সত্যিই এই সমস্ত সারি স্মৃতি থেকে মুছতে চান , বা আপনি এগুলি বাদ দিতে চান? উত্তর ব্যবহার ক্ষেত্রে পৃথক।
মাইকেলচিরিকো

উত্তর:


125

ভাল প্রশ্ন. data.tableএখনও রেফারেন্স দ্বারা সারি মুছতে পারে না।

data.tableআপনারা যেমন কলাম পয়েন্টারগুলির ভেক্টরকে অতিরিক্ত বরাদ্দ করে রেফারেন্স সহ কলামগুলি যুক্ত করতে এবং মুছতে পারে। সারিগুলির জন্য অনুরূপ কিছু করার এবং দ্রুত insertএবং এর অনুমতি দেওয়ার পরিকল্পনা রয়েছে delete। একটি সারি মুছুন ব্যবহার করবেmemmove ফেলা সারিগুলির পরে আইটেমগুলি (প্রতিটি কলামে) আপ করার জন্য সি । টেবিলের মাঝখানে একটি সারি মুছে ফেলা এখনও এসকিউএল-র মতো একটি সারি স্টোরের ডাটাবেসের তুলনায় বেশ অযোগ্য হবে যা এই সারিগুলি সারণীতে যেখানেই থাকুক না কেন দ্রুত সন্নিবেশ এবং সারিগুলি মুছে ফেলার জন্য আরও উপযুক্ত। তবে তবুও, মুছে ফেলা সারিগুলি ছাড়াই কোনও নতুন বৃহত অবজেক্টটি অনুলিপি করার চেয়ে অনেক দ্রুত হবে।

অন্যদিকে,,-বরাদ্দ উপর থেকে কলাম ভেক্টর হবে সারি ঢোকানো যেতে পারে (এবং মুছে ফেলা হয়েছে) শেষে , ঝটপট; যেমন, একটি ক্রমবর্ধমান সময়ের সিরিজ series


এটি একটি সমস্যা হিসাবে দায়ের করা হয়েছে: রেফারেন্স দ্বারা সারি মুছুন


1
@ ম্যাথু ডাওল এই সম্পর্কে কিছু খবর আছে?
স্থির

15
@ তবুও আমি মনে করি আমার 37 টি বাগ ঠিক করা উচিত এবং freadপ্রথমে শেষ করা উচিত । এরপরে এটি বেশ উঁচুতে।
ম্যাট ডাউলে

15
@ ম্যাথেজডোওল নিশ্চিত, আপনি যা করছেন তার জন্য আবারও ধন্যবাদ।
স্ট্যাটিক্যান্ট

1
@ আরব্যাট সঠিক DT[b<8 & a>3]একটি নতুন ডেটা টেবিল দেয়। আমরা যুক্ত করতে চাই delete(DT, b>=8 | a<=3)এবং DT[b>=8 | a<=8, .ROW:=NULL]। পরেরটির সুবিধাটি হ'ল []সারি সংখ্যাগুলির মতো অন্যান্য বৈশিষ্ট্যগুলির সাথে একত্রিত হবে i, যোগদান করবে iএবং অপ্টিমাইজেশন rollথেকে উপকৃত হবে [i,j,by]
ম্যাট ডাউল

2
পছন্দ করেছেন অবদান স্বাগত। আমি গাইড করতে ইচ্ছুক। এটি সি দক্ষতা প্রয়োজন - আবার, আমি গাইড করতে ইচ্ছুক।
ম্যাট ডাওল

29

মেমরির ব্যবহারের জন্য আমি যে পদ্ধতিটি গ্রহণ করেছি তা স্থানটিতে মুছে ফেলার অনুরূপ a যথাযথ সি মেমমোভ দ্রবণ হিসাবে তত দ্রুত নয়, তবে মেমরির ব্যবহারটি আমি এখানে যত্নবান। এটার মতো কিছু:

DT = data.table(col1 = 1:1e6)
cols = paste0('col', 2:100)
for (col in cols){ DT[, (col) := 1:1e6] }
keep.idxs = sample(1e6, 9e5, FALSE) # keep 90% of entries
DT.subset = data.table(col1 = DT[['col1']][keep.idxs]) # this is the subsetted table
for (col in cols){
  DT.subset[, (col) := DT[[col]][keep.idxs]]
  DT[, (col) := NULL] #delete
}

5
+1 চমৎকার মেমরি দক্ষ পদ্ধতির। সুতরাং আদর্শভাবে আমাদের রেফারেন্সের মাধ্যমে সারিগুলির একটি সেট মুছতে হবে আসলে আমরা তা করি না, আমি এটি ভাবিনি। memmoveশূন্যস্থানগুলি বাড়াতে এটি একটি সিরিজ হতে হবে, তবে এটি ঠিক আছে।
ম্যাট ডাউলে

এটি কি কোনও ফাংশন হিসাবে কাজ করবে, বা কোনও ফাংশনে ব্যবহার এবং ফিরে আসার কারণে এটি মেমরির অনুলিপি তৈরি করতে বাধ্য হয়?
রাসেলপিয়ের

1
এটি কোনও ফাংশনে কাজ করবে, যেহেতু ডেটা.টেলগুলি সর্বদা উল্লেখ থাকে।
vc273

1
ধন্যবাদ, সুন্দর। সামান্য কিছুটা গতি বাড়ানোর জন্য (বিশেষত অনেকগুলি কলাম সহ) আপনি পরিবর্তন DT[, col:= NULL, with = F]করেনset(DT, NULL, col, NULL)
মিশেল

2
আইডিয়োম পরিবর্তন এবং "সতর্কতার সাথে" FALSE একসাথে প্রকাশের আলোকে হালনাগাদ করা: = অক্টোবর 2014 এ প্রকাশিত v1.9.4 এ অবহেলা করা হয়েছিল Please , দ্বারা = ক] পরিবর্তনশীল মাইভারে রাখা কলামের নাম (গুলি) নির্ধারণের জন্য See দেখুন? ': =' অন্যান্য উদাহরণের জন্য 2014
ফ্রাঙ্ক

6

@ Vc273 এর উত্তর এবং @ ফ্র্যাঙ্কের প্রতিক্রিয়ার ভিত্তিতে একটি কার্যকারী ফাংশন এখানে দেওয়া হয়েছে।

delete <- function(DT, del.idxs) {           # pls note 'del.idxs' vs. 'keep.idxs'
  keep.idxs <- setdiff(DT[, .I], del.idxs);  # select row indexes to keep
  cols = names(DT);
  DT.subset <- data.table(DT[[1]][keep.idxs]); # this is the subsetted table
  setnames(DT.subset, cols[1]);
  for (col in cols[2:length(cols)]) {
    DT.subset[, (col) := DT[[col]][keep.idxs]];
    DT[, (col) := NULL];  # delete
  }
   return(DT.subset);
}

এবং এর ব্যবহারের উদাহরণ:

dat <- delete(dat,del.idxs)   ## Pls note 'del.idxs' instead of 'keep.idxs'

যেখানে "ডাট" একটি ডেটা টেবিল। 1.4M সারি থেকে 14k সারিগুলি সরানো আমার ল্যাপটপে 0.25 সেকেন্ড সময় নেয়।

> dim(dat)
[1] 1419393      25
> system.time(dat <- delete(dat,del.idxs))
   user  system elapsed 
   0.23    0.02    0.25 
> dim(dat)
[1] 1404715      25
> 

পুনশ্চ. যেহেতু আমি এসও তে নতুন, আমি @ vc273 এর থ্রেডে মন্তব্য যোগ করতে পারিনি :-(


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

আপনি কেন রেফারেন্স দিয়ে এটি করেন তা আমি বুঝতে পারি না তবে পরে একটি অ্যাসাইনমেন্ট ডেটা
স্ক্যান

1
@ সাকান, এই অ্যাসাইনমেন্টটি "ডাট" কে পরিবর্তিত ডেটাতে নির্দেশ করার জন্য নির্ধারিত করে t <- অ্যাসমেন্টমেন্ট রিটার্ন ডেটার অনুলিপি করে না, কেবল এটির জন্য নতুন নাম নির্ধারণ করে। লিঙ্ক
জার্নো পি।

@ ফ্র্যাঙ্ক, আপনি যে অদ্ভুততা নির্দেশ করেছেন তার জন্য আমি ফাংশনটি আপডেট করেছি।
জার্নো পি।

ঠিক আছে ধন্যবাদ. আমি মন্তব্যটি ছেড়ে দিচ্ছি যেহেতু আমি এখনও মনে করি যে এটি একটি প্রজননযোগ্য উদাহরণের পরিবর্তে কনসোল আউটপুট প্রদর্শন এখানে উত্সাহিত নয় worth এছাড়াও, একটি একক মানদণ্ড এতটা তথ্যপূর্ণ নয়। আপনি যদি সাবসেটিংয়ের জন্য নেওয়া সময়ও মাপা করেন তবে এটি আরও তথ্যবহুল হবে (যেহেতু আমাদের বেশিরভাগ লোক স্বজ্ঞাতভাবে জানে না যে এটি কতটা সময় নেয়, আপনার কমপিউলে কতটা সময় নেয়) less যাইহোক, আমি বোঝাতে চাইছি না এটি একটি খারাপ উত্তর; আমি এর অন্যতম প্রচারক।
ফ্রাঙ্ক

4

পরিবর্তে বা NULL এ সেট করার চেষ্টা করে, NA এ সেট করার চেষ্টা করুন (প্রথম কলামের জন্য এনএ-টাইপের সাথে মিলছে)

set(DT,1:2, 1:3 ,NA_character_)

3
হ্যাঁ, আমি অনুমান করি যে কাজ করে। আমার সমস্যাটি হ'ল আমার কাছে প্রচুর ডেটা রয়েছে এবং আমি NA এর সাথে ঠিক সেই সারিগুলি থেকে মুক্তি পেতে চাই, সম্ভবত এই সারিগুলি থেকে মুক্তি পেতে ডিটি অনুলিপি না করেই থাকতে হবে। যাইহোক আপনার মন্তব্যের জন্য ধন্যবাদ!
ফ্লোরিয়ান ওসওয়াল্ড

4

বিষয়টি এখনও আকর্ষণীয় অনেক লোক (আমার অন্তর্ভুক্ত)।

ওটা সম্পর্কে কি? আমি পূর্বে বর্ণিত কোড এবং কোডটি assignপ্রতিস্থাপন করতাম glovalenv। মূল পরিবেশটি ক্যাপচার করা ভাল তবে কমপক্ষে globalenvএতে মেমরি দক্ষ এবং রেফ দ্বারা পরিবর্তনের মতো কাজ করে।

delete <- function(DT, del.idxs) 
{ 
  varname = deparse(substitute(DT))

  keep.idxs <- setdiff(DT[, .I], del.idxs)
  cols = names(DT);
  DT.subset <- data.table(DT[[1]][keep.idxs])
  setnames(DT.subset, cols[1])

  for (col in cols[2:length(cols)]) 
  {
    DT.subset[, (col) := DT[[col]][keep.idxs]]
    DT[, (col) := NULL];  # delete
  }

  assign(varname, DT.subset, envir = globalenv())
  return(invisible())
}

DT = data.table(x = rep(c("a", "b", "c"), each = 3), y = c(1, 3, 6), v = 1:9)
delete(DT, 3)

কেবল স্পষ্ট করে বলতে গেলে, এটি রেফারেন্সের মাধ্যমে মুছে ফেলা হয় না (ভিত্তিক address(DT); delete(DT, 3); address(DT)), যদিও এটি কোনও দিক থেকে দক্ষ হতে পারে।
ফ্রাঙ্ক

1
না এটা না। এটি আচরণ অনুকরণ করে এবং স্মৃতিশক্তি দক্ষ। এই কারণেই আমি বলেছিলাম: এটির মতো কাজ করে । তবে কঠোরভাবে বললে আপনি ঠিক ঠিকানাটি বদলে গেছেন।
জেআরআর

3

এখানে আমি ব্যবহার করেছি কিছু কৌশল। আমি বিশ্বাস করি একটি .ROW ফাংশন আসতে পারে। নীচের এই পদ্ধতির কোনওটিই দ্রুত নয়। সাবলেট বা ফিল্টারিংয়ের বাইরে কিছু কৌশল এই। আমি ডিবিএর মতো চিন্তা করার চেষ্টা করেছি কেবল ডেটা পরিষ্কার করার চেষ্টা করছি। উপরে উল্লিখিত হিসাবে, আপনি ডেটাতে সারিগুলি নির্বাচন বা সরাতে পারেন able টেবিল:

data(iris)
iris <- data.table(iris)

iris[3] # Select row three

iris[-3] # Remove row three

You can also use .SD to select or remove rows:

iris[,.SD[3]] # Select row three

iris[,.SD[3:6],by=,.(Species)] # Select row 3 - 6 for each Species

iris[,.SD[-3]] # Remove row three

iris[,.SD[-3:-6],by=,.(Species)] # Remove row 3 - 6 for each Species

দ্রষ্টব্য: .এসডি মূল ডেটার একটি উপসেট তৈরি করে এবং আপনাকে জে বা পরবর্তী ডেটা.ট্যাবেলে বেশ কিছুটা কাজ করতে দেয়। Https://stackoverflow.com/a/47406952/305675 দেখুন । এখানে আমি সেপাল দৈর্ঘ্যের দ্বারা আমার আইরিজকে অর্ডার করেছি, একটি নির্দিষ্ট সেপাল নিন। সর্বনিম্ন হিসাবে দৈর্ঘ্য করুন, সমস্ত প্রজাতির শীর্ষ তিনটি (সেপাল দৈর্ঘ্যের দ্বারা) নির্বাচন করুন এবং তার সাথে সংযুক্ত সমস্ত তথ্য ফিরিয়ে দিন:

iris[order(-Sepal.Length)][Sepal.Length > 3,.SD[1:3],by=,.(Species)]

সর্বোপরি সমস্ত পন্থাগুলি একটি ডেটা পুনরায় অর্ডার করে r আপনি কোনও ডেটা স্থানান্তর করতে পারেন able পুরানো সারিগুলি সরিয়ে বা প্রতিস্থাপন করতে পারেন যা এখন কলাম স্থানান্তরিত হয়েছে। ': = NULL' ব্যবহার করে কোনও ট্রান্সপোজড সারি অপসারণ করতে, পরবর্তী কলামের নামটিও সরানো হবে:

m_iris <- data.table(t(iris))[,V3:=NULL] # V3 column removed

d_iris <- data.table(t(iris))[,V3:=V2] # V3 column replaced with V2

আপনি যখন ডেটা স্থানান্তর করেন ra ফ্রেমটি কোনও ডেটা.ট্যাবেলে ফিরে আসে, আপনি মূল ডেটা থেকে নাম পরিবর্তন করতে পারেন able সারণি এবং মুছে ফেলার ক্ষেত্রে শ্রেণি বৈশিষ্ট্য পুনরুদ্ধার করতে পারেন। এখনই স্থানান্তরিত ডেটাতে ": = NULL" প্রয়োগ করা সমস্ত টেক্সট ক্লাস তৈরি করে।

m_iris <- data.table(t(d_iris));
setnames(d_iris,names(iris))

d_iris <- data.table(t(m_iris));
setnames(m_iris,names(iris))

আপনি কেবল নকল সারিগুলি মুছে ফেলতে চাইতে পারেন যা আপনি কী দিয়ে বা ছাড়াই করতে পারেন:

d_iris[,Key:=paste0(Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species)]     

d_iris[!duplicated(Key),]

d_iris[!duplicated(paste0(Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species)),]  

'.I' দিয়ে একটি ইনক্রিমেন্টাল কাউন্টার যুক্ত করাও সম্ভব। এরপরে আপনি সদৃশ কী বা ক্ষেত্রগুলি অনুসন্ধান করতে এবং কাউন্টারের সাহায্যে রেকর্ড সরিয়ে এগুলি সরাতে পারেন। এটি গণনাগতভাবে ব্যয়বহুল, তবে কিছু সুবিধা রয়েছে যেহেতু আপনি মুছে ফেলা লাইনগুলি মুদ্রণ করতে পারেন।

d_iris[,I:=.I,] # add a counter field

d_iris[,Key:=paste0(Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species)]

for(i in d_iris[duplicated(Key),I]) {print(i)} # See lines with duplicated Key or Field

for(i in d_iris[duplicated(Key),I]) {d_iris <- d_iris[!I == i,]} # Remove lines with duplicated Key or any particular field.

আপনি কেবল 0 সে বা এনএ দিয়ে একটি সারি পূরণ করতে পারেন এবং সেগুলি মুছতে আই কোয়েরি ব্যবহার করতে পারেন:

 X 
   x v foo
1: c 8   4
2: b 7   2

X[1] <- c(0)

X
   x v foo
1: 0 0   0
2: b 7   2

X[2] <- c(NA)
X
    x  v foo
1:  0  0   0
2: NA NA  NA

X <- X[x != 0,]
X <- X[!is.na(x),]

এটি সত্যই প্রশ্নের উত্তর দেয় না (রেফারেন্স দ্বারা অপসারণ সম্পর্কে) এবং tডেটা.ফ্রেমে ব্যবহার করা সাধারণত ভাল ধারণা নয়; str(m_iris)সমস্ত ডেটা স্ট্রিং / অক্ষর হয়ে গেছে তা পরীক্ষা করে দেখুন। বিটিডাব্লু, আপনি d_iris[duplicated(Key), which = TRUE]কাউন্টার কলাম না করেও সারি নম্বর পেতে পারেন ।
ফ্রাঙ্ক

1
হ্যাঁ তুমিই ঠিক. আমি বিশেষভাবে প্রশ্নের উত্তর দেই না। তবে রেফারেন্স অনুসারে একটি সারি সরানোর আনুষ্ঠানিক কার্যকারিতা বা ডকুমেন্টেশন নেই এবং অনেক লোক ঠিক এই কাজটি করার জন্য জেনেরিক কার্যকারিতা খুঁজছেন এই পোস্টে আসতে চলেছে। আমরা কীভাবে একটি সারি অপসারণ করতে পারি তার প্রশ্নের উত্তর দেওয়ার জন্য একটি পোস্ট তৈরি করতে পারি। স্ট্যাক ওভারফ্লো খুব দরকারী এবং প্রশ্নের উত্তর সঠিক রাখার প্রয়োজনীয়তা আমি সত্যিই বুঝতে পারি। কখনও কখনও যদিও, আমি মনে করি এসও এই ক্ষেত্রে একটু ফ্যাসিবাদী হতে পারে ... তবে সম্ভবত এটির জন্য ভাল কারণ থাকতে পারে।
rferrisx

ঠিক আছে, ব্যাখ্যা করার জন্য ধন্যবাদ। আমি মনে করি আপাতত এখানে আমাদের আলোচনা যে কেউ এই ক্ষেত্রে বিভ্রান্ত হয় তার পক্ষে একটি সাইনপোস্টই যথেষ্ট।
ফ্রাঙ্ক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.