`স্তরের <-` (এটি কী জাদু?


114

অন্য প্রশ্নের উত্তরে, @ মারেক নিম্নলিখিত সমাধান পোস্ট করেছেন: https://stackoverflow.com/a/10432263/636656

dat <- structure(list(product = c(11L, 11L, 9L, 9L, 6L, 1L, 11L, 5L, 
                                  7L, 11L, 5L, 11L, 4L, 3L, 10L, 7L, 10L, 5L, 9L, 8L)), .Names = "product", row.names = c(NA, -20L), class = "data.frame")

`levels<-`(
  factor(dat$product),
  list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
  )

যা আউটপুট হিসাবে উত্পাদন করে:

 [1] Generic Generic Bayer   Bayer   Advil   Tylenol Generic Advil   Bayer   Generic Advil   Generic Advil   Tylenol
[15] Generic Bayer   Generic Advil   Bayer   Bayer  

এটি কেবল কোনও ভেক্টরের প্রিন্টআউট, সুতরাং এটি সঞ্চয় করতে আপনি আরও বিভ্রান্তিকর করতে পারেন:

res <- `levels<-`(
  factor(dat$product),
  list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
  )

স্পষ্টতই এটি স্তরগুলির ফাংশনটিতে এক ধরণের কল, তবে এখানে কী করা হচ্ছে তা আমার কোনও ধারণা নেই। এই জাতীয় যাদুবিদ্যার শব্দটি কী এবং আমি কীভাবে এই ডোমেনে আমার যাদুকরী ক্ষমতা বাড়াতে পারি?


1
এছাড়াও আছে names<-এবং [<-
হুন

1
এছাড়াও, আমি অন্যান্য প্রশ্নে এ সম্পর্কে অবাক হয়েছি কিন্তু জিজ্ঞাসা করিনি: ন্যায়বিচারের structure(...)পরিবর্তে নির্মাণের কোনও কারণ আছে data.frame(product = c(11L, 11L, ..., 8L))কি? (যদি সেখানে কোনও যাদুঘটিত ঘটে থাকে তবে আমি এটিও চালিত করে তুলতে চাই!)
হুন

2
এটি "levels<-"ফাংশনটির জন্য একটি কল function (x, value) .Primitive("levels<-"):, সাজানোর মতো X %in% Yএকটি সংক্ষেপণ "%in%"(X, Y)
বেনবার্নস

2
গঠনকর উদাহরণের জন্য @dbaupp খুব কুশলী: stackoverflow.com/questions/5963269/...
আরি বি ফ্রিডম্যান

8
আমার ধারণা নেই কারও পক্ষে এটি গঠনমূলক না বলে বন্ধ করার পক্ষে কেন ভোট দিয়েছেন? প্রশ্নটির একটি খুব সুস্পষ্ট উত্তর রয়েছে: উদাহরণে ব্যবহৃত সিনট্যাক্সটির অর্থ কী এবং এটি আর-তে কীভাবে কাজ করে?
গ্যাভিন সিম্পসন

উত্তর:


104

এখানে উত্তরগুলি ভাল, তবে তারা একটি গুরুত্বপূর্ণ বিষয় অনুপস্থিত। আমি এটি চেষ্টা এবং বর্ণনা করতে দিন।

আর একটি কার্যকরী ভাষা এবং এটির বস্তুগুলিকে পরিবর্তন করতে পছন্দ করে না। তবে এটি প্রতিস্থাপন ফাংশনগুলি ব্যবহার করে অ্যাসাইনমেন্ট স্টেটমেন্টগুলির অনুমতি দেয়:

levels(x) <- y

সমতুল্য

x <- `levels<-`(x, y)

কৌশলটি হ'ল, এই পুনর্লিখনটি দ্বারা করা হয়েছে <-; এটি দ্বারা করা হয় না levels<-levels<-কেবল একটি নিয়মিত ফাংশন যা একটি ইনপুট নেয় এবং একটি আউটপুট দেয়; এটি কিছুই পরিবর্তন করে না।

এর একটি পরিণতি হ'ল উপরের নিয়ম অনুসারে <-অবশ্যই পুনরাবৃত্ত হওয়া উচিত:

levels(factor(x)) <- y

হয়

factor(x) <- `levels<-`(factor(x), y)

হয়

x <- `factor<-`(x, `levels<-`(factor(x), y))

এটি একধরনের সুন্দর যে এই খাঁটি-কার্যকরী রূপান্তর (একেবারে শেষ অবধি, যেখানে অ্যাসাইনমেন্টটি ঘটে) অপরিহার্য ভাষায় কোনও অ্যাসাইনমেন্ট কী হবে তার সমতুল্য। যদি আমি সঠিকভাবে মনে রাখি তবে কার্যকরী ভাষায় এই নির্মাণকে লেন্স বলা হয়।

তবে তারপরে, আপনি প্রতিস্থাপনের ক্রিয়াগুলি যেমন একবার সংজ্ঞায়িত করার পরে, আপনি levels<-অন্যটি পাবেন, অপ্রত্যাশিত উইন্ডফোল: আপনার কাছে কেবল অ্যাসাইনমেন্টগুলি করার ক্ষমতা নেই, আপনার একটি কার্যকর ফাংশন রয়েছে যা একটি ফ্যাক্টর গ্রহণ করে এবং বিভিন্ন স্তরের সাথে অন্য একটি উপাদান দেয়। এটি সম্পর্কে "অ্যাসাইনমেন্ট" এর আসলে কিছুই নেই!

সুতরাং, আপনি যে কোডটি বর্ণনা করছেন তা হ'ল এই অন্য ব্যাখ্যাটি ব্যবহার করে levels<-। আমি স্বীকার করি যে নামটি levels<-কিছুটা বিভ্রান্তিকর কারণ এটি একটি কার্যভার প্রস্তাব দেয় তবে এটি যা চলছে তা নয়। কোডটি কেবল এক ধরণের পাইপলাইন সেট আপ করছে:

  • শুরু করা dat$product

  • এটিকে একটি ফ্যাক্টরে রূপান্তর করুন

  • স্তর পরিবর্তন করুন

  • যে স্টোর res

ব্যক্তিগতভাবে, আমি মনে করি কোডের লাইনটি সুন্দর;)


33

কোন জাদু নয়, ঠিক কীভাবে (উপ) অ্যাসাইনমেন্ট ফাংশনগুলি সংজ্ঞায়িত করা হয়। levels<-এটি কিছুটা আলাদা কারণ এটি (সাব) একটি উপাদানটির বৈশিষ্ট্য নির্ধারণের জন্য আদিম, তারা উপাদানগুলি নয়। এই ধরণের কার্যকারিতার প্রচুর উদাহরণ রয়েছে:

`<-`              # assignment
`[<-`             # sub-assignment
`[<-.data.frame`  # sub-assignment data.frame method
`dimnames<-`      # change dimname attribute
`attributes<-`    # change any attributes

অন্যান্য বাইনারি অপারেটরদেরও এর মতো বলা যেতে পারে:

`+`(1,2)  # 3
`-`(1,2)  # -1
`*`(1,2)  # 2
`/`(1,2)  # 0.5

এখন যেহেতু আপনি জানেন যে, এরকম কিছু আপনার হৃদয়কে সত্যই উড়িয়ে দেবে:

Data <- data.frame(x=1:10, y=10:1)
names(Data)[1] <- "HI"              # How does that work?!? Magic! ;-)

1
আপনি যখন স্বাভাবিক উপায়ের চেয়ে ফাংশনগুলিকে সেইভাবে কল করতে বোধ করেন তখন আপনি আরও কিছুটা ব্যাখ্যা করতে পারেন? আমি লিঙ্কযুক্ত প্রশ্নে @ মারেকের উদাহরণ দিয়ে কাজ করছি, তবে এটি আরও স্পষ্ট করে ব্যাখ্যা করতে সহায়তা করবে।
ড্র স্টিইন

4
@ ড্রুস্টেন: কোডের স্পষ্টতা / পঠনযোগ্যতার কারণে আমি বলব এটি কখনই বোধগম্য `levels<-`(foo,bar)হয় না কারণ এটি একই রকম levels(foo) <- bar। @ মারেকের উদাহরণ ব্যবহার করা: এর `levels<-`(as.factor(foo),bar)মত foo <- as.factor(foo); levels(foo) <- bar
জোশুয়া উলিরিচ

সুন্দর তালিকা। আপনি কি মনে করেন না যে levels<-এটি আসলেই সংক্ষিপ্ত attr<-(x, "levels") <- value, বা কমপক্ষে এটি সম্ভবত কোনও আদিম রূপান্তরিত হয়ে সি-কোডের হাতে দেওয়ার আগ পর্যন্ত ছিল।
আইআরটিএফএম

30

"ম্যাজিক" এর কারণ হ'ল "অ্যাসাইনমেন্ট" ফর্মটিতে কাজ করার জন্য অবশ্যই আসল পরিবর্তনশীল থাকতে হবে। এবং factor(dat$product)কিছুই কিছু বরাদ্দ করা হয়নি।

# This works since its done in several steps
x <- factor(dat$product)
levels(x) <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
x

# This doesn't work although it's the "same" thing:
levels(factor(dat$product)) <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
# Error: could not find function "factor<-"

# and this is the magic work-around that does work
`levels<-`(
  factor(dat$product),
  list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
  )

+1 আমি মনে করি এটি প্রথমে ফ্যাক্টারে রূপান্তর করা পরিষ্কার হবে, তারপরে স্তরগুলি একটি within()এবং transform()কলের মাধ্যমে প্রতিস্থাপন করা হত যদি এইভাবে পরিবর্তিত বস্তুটি ফিরে আসে এবং বরাদ্দ করা হত।
গ্যাভিন সিম্পসন

4
@ গ্যাভিনসিম্পসন - আমি একমত হই, আমি কেবল যাদুটিই ব্যাখ্যা করি, আমি এটিকে রক্ষা করি না ;-)
টমি

16

ব্যবহারকারীর-কোডের জন্য আমি অবাক হয়েছি কেন এই জাতীয় ভাষার হেরফেরটি এত ব্যবহৃত হয়? আপনি কি জিজ্ঞাসা করেন এটি কোন যাদুটি এবং অন্যরা উল্লেখ করেছে যে আপনি নামটি প্রতিস্থাপন ফাংশনটি কল করছেন levels<-। বেশিরভাগ মানুষের জন্য এটি যাদু এবং সত্যই ব্যবহৃত উদ্দেশ্য হ'ল levels(foo) <- bar

আপনি যে ব্যবহার-কেসটি দেখান তা পৃথক কারণ productবৈশ্বিক পরিবেশে এটি বিদ্যমান নেই তাই এটি কেবলমাত্র স্থানীয় পরিবেশে কলটির অস্তিত্বের জন্য থাকে levels<-সুতরাং আপনি যে পরিবর্তনটি করতে চান তা স্থির হয় না - এর কোনও পুনরায় নিয়োগ হয়নি dat

এই পরিস্থিতিতে, within() ব্যবহার করার জন্য আদর্শ ফাংশন। আপনি স্বাভাবিকভাবে লিখতে ইচ্ছুক হবে

levels(product) <- bar

আর তে তবে অবশ্যই productএকটি বস্তু হিসাবে বিদ্যমান নেই। within()এটি কাছাকাছি যায় কারণ এটি পরিবেশটি সেট করে যা আপনি আপনার আর কোডের বিরুদ্ধে চালনা করতে চান এবং সেই পরিবেশের মধ্যে আপনার অভিব্যক্তির মূল্যায়ন করে। কল থেকে রিটার্ন অবজেক্টকে নির্ধারণ করা within()সঠিকভাবে পরিবর্তিত ডেটা ফ্রেমে সাফল্য লাভ করে।

এখানে একটি উদাহরণ রয়েছে (আপনাকে নতুন তৈরি করার দরকার নেই datX- আমি কেবল এটি করি যাতে মধ্যস্থতাকারী পদক্ষেপগুলি শেষে থাকে)

## one or t'other
#dat2 <- transform(dat, product = factor(product))
dat2 <- within(dat, product <- factor(product))

## then
dat3 <- within(dat2, 
               levels(product) <- list(Tylenol=1:3, Advil=4:6, 
                                       Bayer=7:9, Generic=10:12))

যা দেয়:

> head(dat3)
  product
1 Generic
2 Generic
3   Bayer
4   Bayer
5   Advil
6 Tylenol
> str(dat3)
'data.frame':   20 obs. of  1 variable:
 $ product: Factor w/ 4 levels "Tylenol","Advil",..: 4 4 3 3 2 1 4 2 3 4 ...

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

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