নিকটতম 10 (বা 100 বা এক্স) পর্যন্ত কী করে যাবে?


95

আমি ডেটা প্লট করার জন্য একটি ফাংশন লিখছি। আমি y- অক্ষের জন্য একটি দুর্দান্ত গোল সংখ্যা উল্লেখ করতে চাই maxযা ডেটাসেটের সর্বাধিকের চেয়ে বড়।

বিশেষত, আমি একটি ফাংশন চাই fooযা নিম্নলিখিতগুলি সম্পাদন করে:

foo(4) == 5
foo(6.1) == 10 #maybe 7 would be better
foo(30.1) == 40
foo(100.1) == 110 

আমি যতদূর পেরেছি

foo <- function(x) ceiling(max(x)/10)*10

নিকটতম 10 এ গোল করার জন্য, তবে এটি স্বেচ্ছাসেবী বৃত্তাকার অন্তরগুলির জন্য কাজ করে না।

আর-তে এটি করার আরও ভাল উপায় আছে কি?


প্লট করার সময় আর ডিফল্ট আচরণটি প্রতিটি দিকের ডেটার সীমা ছাড়িয়ে plot 4% সীমাবদ্ধ করে দেয়। এটি যদি আপনার সন্তুষ্ট না হয় তবে কেবল এমন কিছু লিখুন যা একটি উচ্চ বা নিম্ন% এর বাইরে চলে যায়?
জোড়ান

@ জোর তথ্যের জন্য ধন্যবাদ, তবে আমি একাধিক প্লট চাই যে সকলের অক্ষ অক্ষর সীমা এবং টিক থাকে এবং আমি নিশ্চিত নই যে এটি কীভাবে সহায়তা করে।
আবে

4
ঠিক আছে, আমি এখানে অন্ধকারে ধীরে ধীরে ঘুরে বেড়াচ্ছি, যেহেতু আমি সমস্ত ব্যাকগ্রাউন্ড জানি না। যদি আপনি কেবলমাত্র অন্য একটি প্যারামিটার এক্স যুক্ত করেন এবং 10 এর উভয়কে এক্স দিয়ে প্রতিস্থাপন করেন তবে আপনার ফুও নিকটতম এক্স পর্যন্ত পৌঁছবে Or বা আপনি ফেসিং ব্যবহার করতে পারেন।
জোড়ান

15
আপনি খুঁজছেন ?pretty?
হ্যাডলি

কেন foo(4)==5এবং না 10?
জেমস

উত্তর:


65

আপনি যদি কেবলমাত্র 10 এর নিকটতম শক্তিটি পেতে চান তবে কেবল সংজ্ঞা দিন:

roundUp <- function(x) 10^ceiling(log10(x))

এক্স আসলে ভেক্টর হলে এটিও কার্যকরভাবে কাজ করে:

> roundUp(c(0.0023, 3.99, 10, 1003))
[1] 1e-02 1e+01 1e+01 1e+04

.. তবে আপনি যদি কোনও "সুন্দর" সংখ্যায় গোল করতে চান, আপনাকে প্রথমে একটি "সুন্দর" সংখ্যাটি নির্ধারণ করতে হবে। নিম্নলিখিতটি আমাদের 1 থেকে 10 পর্যন্ত দুর্দান্ত বেস মান সহ ভেক্টর হিসাবে "দুর্দান্ত" সংজ্ঞা দিতে দেয় The

roundUpNice <- function(x, nice=c(1,2,4,5,6,8,10)) {
    if(length(x) != 1) stop("'x' must be of length 1")
    10^floor(log10(x)) * nice[[which(x <= 10^floor(log10(x)) * nice)[[1]]]]
}

এক্স ভেক্টর হলে উপরেরটি কাজ করে না - এখন সন্ধ্যা খুব দেরিতে :)

> roundUpNice(0.0322)
[1] 0.04
> roundUpNice(3.22)
[1] 4
> roundUpNice(32.2)
[1] 40
> roundUpNice(42.2)
[1] 50
> roundUpNice(422.2)
[1] 500

[[সম্পাদনা]]

যদি প্রশ্নটি নির্ধারিত নিকটতম মানের (10 বা 100 এর মতো) গোল করে কীভাবে হয় তবে জেমসের উত্তরটি সবচেয়ে উপযুক্ত বলে মনে হয়। আমার সংস্করণ আপনাকে যে কোনও মান নিতে এবং স্বয়ংক্রিয়ভাবে এটিকে যুক্তিসঙ্গতভাবে "সুন্দর" মান হিসাবে গোল করতে দেয়। উপরের "দুর্দান্ত" ভেক্টরের আরও কয়েকটি ভাল পছন্দগুলি হ'ল:1:10, c(1,5,10), seq(1, 10, 0.1)

যদি আপনার প্লটে আপনার মানগুলির একটি ব্যাপ্তি থাকে, উদাহরণস্বরূপ [3996.225, 40001.893]তবে স্বয়ংক্রিয় পদ্ধতিতে পরিসরের আকার এবং সংখ্যার বিশালতা উভয়ই বিবেচনায় নেওয়া উচিত। এবং হ্যাডলি দ্বারা উল্লিখিত হিসাবে , pretty()ফাংশনটি আপনি চান তা হতে পারে।


4
Vectorize(roundUpNice)বেশ দ্রুত =) যাইহোক +1।
এমবিকিউ

আমি ভাবছিলাম যে যদি মূল মানটি কম হয় তবে রাউন্ডআপ ফাংশনটি অর্ধেক শেষের দিকে সম্পাদনার কোনও উপায় আছে? উদাহরণস্বরূপ, 101-500 এর মধ্যে একটি সংখ্যা 500 এবং রাউটারআপ 501-999 এর মধ্যে 1000 হবে? এর পরিবর্তে সব কিছুর 1000?
হেলেন।

কেবল সুন্দর ভেক্টরটি পরিবর্তন করুন:roundUpNice(501, nice=c(5, 10)) # 1000
টমি

4
আপনি আপনার ফাংশনে লোগারিদম নিয়ে কাজ করার পরে কেবল একটি সতর্কতা, আমার 2 টি কেস হবে, একটি যেখানে আমি পিছনে রাখার আগে লগটিতে x < 0প্রয়োগ করব । আমি সেই পরিস্থিতির জন্যও একটি ব্যতিক্রম যুক্ত করব- x-x = 0
যোহন ওবাদিয়া

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

132

plyrগ্রন্থাগার একটি ফাংশন আছে round_anyযে বেশ rounding সব ধরণের কাজ করতে জেনেরিক হয়। উদাহরণ স্বরূপ

library(plyr)
round_any(132.1, 10)               # returns 130
round_any(132.1, 10, f = ceiling)  # returns 140
round_any(132.1, 5, f = ceiling)   # returns 135

একটি জন্য dplyrপ্রতিস্থাপন, দেখুন: stackoverflow.com/a/46489816/435093
slhck

46

আর এর মধ্যে গোলাকার ফাংশনটি যদি paraণাত্মক হয় তবে অঙ্কগুলির পরামিতিগুলির বিশেষ অর্থ নির্ধারণ করে।

গোল (x, সংখ্যা = 0)

Aণাত্মক সংখ্যার সাথে গোলাকৃতির অর্থ দশটির শক্তির সাথে বৃত্তাকার, সুতরাং উদাহরণস্বরূপ গোল (x, অঙ্কগুলি = -2) নিকটতম শতকে রাউন্ড করুন।

এই নিচের মত একটি ফাংশন পায় মানে চমত্কার বন্ধ আপনি যা জিজ্ঞাসা করা হয় হয়।

foo <- function(x)
{
    round(x+5,-1)
}

আউটপুট নিম্নলিখিত মত দেখাচ্ছে

foo(4)
[1] 10
foo(6.1)
[1] 10
foo(30.1)
[1] 40
foo(100.1)
[1] 110

4
অসাধারণ! আপনার উত্তরটি সঠিক হিসাবে চিহ্নিত করা উচিত!
আলেসান্দ্রো জ্যাকপসন

+1 তবে, @ অ্যালসান্দ্রো আমার উত্তরের ফাংশনগুলি অনেক বেশি বহুমুখী: আপনি কোনও সংখ্যার উপরে বা নিচে যে কোনও বিরতিতে গোল করতে পারেন ।
বনাঞ্চলবিদ

@ তত্ত্ববিদরা ইঙ্গিতটির জন্য আপনাকে ধন্যবাদ! ব্যক্তিগত স্বাদ হিসাবে, আমি সাধারণত একটি ভাষা পছন্দ না করে অন্তর্নির্মিত সমাধান পছন্দ করি।
আলেসান্দ্রো জ্যাকসন

27

কেমন:

roundUp <- function(x,to=10)
{
  to*(x%/%to + as.logical(x%%to))
}

যা দেয়:

> roundUp(c(4,6.1,30.1,100.1))
[1]  10  10  40 110
> roundUp(4,5)
[1] 5
> roundUp(12,7)
[1] 14

4
@दरোকজিগ প্রশ্নটি কিছুটা বিভ্রান্তিকর, আমি এটি "স্বেচ্ছাচারী এক্স" প্রয়োজনীয়তার উপর আলোকপাত করে লিখেছি, তবে স্পষ্টতই সমস্ত প্রত্যাশিত মানগুলি "নিকটতম এক্স পর্যন্ত একক রাউন্ড" সমাধানের দ্বারা উত্পাদিত হতে পারে না। দেখে মনে হয় যে ওপি একটি অক্ষের জন্য মান উত্পাদন করতে চায় তাই prettyসম্ভবত সেরা বিকল্প।
জেমস

4
স্পষ্টতই এই পার্টিতে দেরি হয়েছে, তবে কি to * ceiling(x / to)ক্লিনার হবে না ?
Jared

27

আপনি যদি রাউন্ড () এর ডিজিটস-আর্গুমেন্টে একটি নেতিবাচক সংখ্যা যুক্ত করেন তবে আর, এটি 10, 100 ইত্যাদির গুণকগুলিতে গোল করবে R

    round(9, digits = -1) 
    [1] 10    
    round(89, digits = -1) 
    [1] 90
    round(89, digits = -2) 
    [1] 100

17

যে কোনও সংখ্যার উপরে / নিচে রাউন্ডের যে কোনও নম্বর val

আপনি সহজেই মডুলো অপারেটরটি ব্যবহার করে একটি নির্দিষ্ট বিরতিতে সংখ্যার বৃত্তাকার করতে পারেন %%

কাজ:

round.choose <- function(x, roundTo, dir = 1) {
  if(dir == 1) {  ##ROUND UP
    x + (roundTo - x %% roundTo)
  } else {
    if(dir == 0) {  ##ROUND DOWN
      x - (x %% roundTo)
    }
  }
}

উদাহরণ:

> round.choose(17,5,1)   #round 17 UP to the next 5th
[1] 20
> round.choose(17,5,0)   #round 17 DOWN to the next 5th
[1] 15
> round.choose(17,2,1)   #round 17 UP to the next even number
[1] 18
> round.choose(17,2,0)   #round 17 DOWN to the next even number
[1] 16

কিভাবে এটা কাজ করে:

মডুলো অপারেটর %%প্রথম সংখ্যাটি ২ য় দ্বারা ভাগ করার বাকিটি নির্ধারণ করে। আপনার আগ্রহের সংখ্যার সাথে এই অন্তর অন্তর্ভুক্ত করা বা বিয়োগ করা আপনার পছন্দসই একটি ব্যবধানে মূলত নম্বরটি 'বৃত্তাকার' করতে পারে।

> 7 + (5 - 7 %% 5)       #round UP to the nearest 5
[1] 10
> 7 + (10 - 7 %% 10)     #round UP to the nearest 10
[1] 10
> 7 + (2 - 7 %% 2)       #round UP to the nearest even number
[1] 8
> 7 + (100 - 7 %% 100)   #round UP to the nearest 100
[1] 100
> 7 + (4 - 7 %% 4)       #round UP to the nearest interval of 4
[1] 8
> 7 + (4.5 - 7 %% 4.5)   #round UP to the nearest interval of 4.5
[1] 9

> 7 - (7 %% 5)           #round DOWN to the nearest 5
[1] 5
> 7 - (7 %% 10)          #round DOWN to the nearest 10
[1] 0
> 7 - (7 %% 2)           #round DOWN to the nearest even number
[1] 6

হালনাগাদ:

সুবিধাজনক 2-যুক্তি সংস্করণ:

rounder <- function(x,y) {
  if(y >= 0) { x + (y - x %% y)}
  else { x - (x %% abs(y))}
}

ধনাত্মক yমান roundUp, তবে নেতিবাচক yমানগুলি roundDown:

 # rounder(7, -4.5) = 4.5, while rounder(7, 4.5) = 9.

বা ....

ফাংশন যা স্ট্যান্ডার্ড রাউন্ডিং নিয়মের ভিত্তিতে স্বয়ংক্রিয়ভাবে UP বা DOWN গোল করে:

Round <- function(x,y) {
  if((y - x %% y) <= x %% y) { x + (y - x %% y)}
  else { x - (x %% y)}
}

রাউন্ডিং মানের পরবর্তী দৃষ্টান্তগুলির মধ্যে যদি xমানটি >অর্ধেক হয়ে যায় তবে স্বয়ংক্রিয়ভাবে গোল হয়ে যায় y:

# Round(1.3,1) = 1 while Round(1.6,1) = 2
# Round(1.024,0.05) = 1 while Round(1.03,0.05) = 1.05

আমাকে Roundএক্সেলে Function ROUND(x,y) 'Function that automatically rounds UP or DOWN based on standard rounding rules. 'Automatically rounds up if the "x" value is > halfway between subsequent instances of the rounding value "y": If (y - (Evaluate("Mod(" & x & "," & y & ")"))) <= (Evaluate("Mod(" & x & "," & y & ")")) Then Ans = x + (y - (Evaluate("Mod(" & x & "," & y & ")"))) Else Ans = x - (Evaluate("Mod(" & x & "," & y & ")")) End If ROUND = Ans End Function
ভিবিএতে

@ তবে আমি নিশ্চিত ছিলাম না যে আপনি আমার উত্তরটি বলেছিলেন বা না বলেছেন আপনি জিজ্ঞাসা করার 4 বছর পরে আমি পোস্ট করেছি, তবে আমি মনে করি আপনি আমার উত্তরটি বেশ মার্জিত এবং খুব ভার্সেটাইল খুঁজে পেতে পারেন find আশা করি এটা সাহায্য করবে!
বনাঞ্চল বিশেষজ্ঞ

7

একটি স্বেচ্ছাসেবী সংখ্যার সংখ্যাবৃদ্ধি , যেমন 10 এর গুণগত মান সম্পর্কে , এখানে জেমসের উত্তরের একটি সহজ বিকল্প।

এটি যেকোন আসল সংখ্যাকে ( from) এবং যে কোনও বাস্তব ধনাত্মক সংখ্যাকে ( to) অবধি গোল করবে :

> RoundUp <- function(from,to) ceiling(from/to)*to

উদাহরণ:

> RoundUp(-11,10)
[1] -10
> RoundUp(-0.1,10)
[1] 0
> RoundUp(0,10)
[1] 0
> RoundUp(8.9,10)
[1] 10
> RoundUp(135,10)
[1] 140

> RoundUp(from=c(1.3,2.4,5.6),to=1.1)  
[1] 2.2 3.3 6.6

2

আমি মনে করি আপনার কোডটি কেবলমাত্র একটি ছোট সংশোধন করে দুর্দান্ত কাজ করে:

foo <- function(x, round=10) ceiling(max(x+10^-9)/round + 1/round)*round

এবং আপনার উদাহরণগুলি চালিত:

> foo(4, round=1) == 5
[1] TRUE
> foo(6.1) == 10            #maybe 7 would be better
[1] TRUE
> foo(6.1, round=1) == 7    # you got 7
[1] TRUE
> foo(30.1) == 40
[1] TRUE
> foo(100.1) == 110
[1] TRUE
> # ALL in one:
> foo(c(4, 6.1, 30.1, 100))
[1] 110
> foo(c(4, 6.1, 30.1, 100), round=10)
[1] 110
> foo(c(4, 6.1, 30.1, 100), round=2.3)
[1] 101.2

আমি আপনার কার্যটি দুটি উপায়ে পরিবর্তন করেছি:

  • দ্বিতীয় যুক্তি যুক্ত করা হয়েছে (আপনার নির্দিষ্ট এক্সের জন্য )
  • আপনি যদি একটি বৃহত সংখ্যা চান তবে একটি স্বল্প মূল্য (( =1e-09সংশোধন করতে নির্দ্বিধায়!) যোগ করুন addedmax(x)

1

আপনি যদি সর্বদা নিকটতম এক্স পর্যন্ত কোনও সংখ্যাটি গোল করতে চান তবে আপনি এই ceilingফাংশনটি ব্যবহার করতে পারেন :

#Round 354 up to the nearest 100:
> X=100
> ceiling(354/X)*X
[1] 400

#Round 47 up to the nearest 30:
> Y=30
> ceiling(47/Y)*Y
[1] 60

একইভাবে, আপনি যদি সর্বদা গোল হয়ে যেতে চান তবে floorফাংশনটি ব্যবহার করুন । আপনি যদি নিকটস্থ Z তে কেবল উপরের দিকে বা নীচে নামাতে চান তবে roundপরিবর্তে ব্যবহার করুন।

> Z=5
> round(367.8/Z)*Z
[1] 370
> round(367.2/Z)*Z
[1] 365

0

টমির উত্তরের একটি আপগ্রেড সংস্করণ আপনি পাবেন যা বেশ কয়েকটি ক্ষেত্রে বিবেচনা করে:

  • নিম্ন বা উচ্চতর গণ্ডির মধ্যে নির্বাচন করা
  • নেতিবাচক এবং শূন্য মান গ্রহণ করা
  • আপনি যদি ফাংশনটি ভিন্নভাবে ছোট এবং বড় সংখ্যককে গোল করতে চান তবে দুটি ভিন্ন সুন্দর স্কেল। উদাহরণ: 4 গোলাকার হবে 0 এবং 400 টি 400 এ গোল করা হবে।

কোডের নীচে:

round.up.nice <- function(x, lower_bound = TRUE, nice_small=c(0,5,10), nice_big=c(1,2,3,4,5,6,7,8,9,10)) {
  if (abs(x) > 100) {
    nice = nice_big
  } else {
    nice = nice_small
  }
  if (lower_bound == TRUE) {
    if (x > 0) {
      return(10^floor(log10(x)) * nice[[max(which(x >= 10^floor(log10(x)) * nice))[[1]]]])
    } else if (x < 0) {
      return(- 10^floor(log10(-x)) * nice[[min(which(-x <= 10^floor(log10(-x)) * nice))[[1]]]])
    } else {
      return(0)
    }
  } else {
    if (x > 0) {
      return(10^floor(log10(x)) * nice[[min(which(x <= 10^floor(log10(x)) * nice))[[1]]]])
    } else if (x < 0) {
      return(- 10^floor(log10(-x)) * nice[[max(which(-x >= 10^floor(log10(-x)) * nice))[[1]]]])
    } else {
      return(0)
    }
  }
}

এর ডিফল্ট আউটপুটটি বৃত্তাকার ডাউন:> round.up.nice(.01) [1] 0 > round.up.nice(4.5) [1] 0 > round.up.nice(56) [1] 50
জেসি

আমি মনে করি সমস্যার একটি অংশ এটি nice_bigএবং nice_smallপিছনের দিক দিয়ে সংজ্ঞায়িত করা হয়েছে, (যদি আমরা তাদের ফাংশনটিতে ফ্লিপ করি তবে round.up.nice(4.5)হয়ে যায় 4) তবে এটি এখনও গোলাকার হয়।
জেসি

0

আমি কোনও বাহ্যিক গ্রন্থাগার বা ক্রিপ্টিক বৈশিষ্ট্য ব্যবহার না করে এটি চেষ্টা করেছি এবং এটি কার্যকর!

আশা করি এটি কাউকে সাহায্য করবে।

ceil <- function(val, multiple){
  div = val/multiple
  int_div = as.integer(div)
  return (int_div * multiple + ceiling(div - int_div) * multiple)
}

> ceil(2.1, 2.2)
[1] 2.2
> ceil(3, 2.2)
[1] 4.4
> ceil(5, 10)
[1] 10
> ceil(0, 10)
[1] 0
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.