জ্ঞাত ন্যূনতম এবং সর্বাধিক মান সহ কীভাবে সংখ্যার ব্যাপ্তি তৈরি করতে হয়


230

সুতরাং আমি কীভাবে একটি ব্যাপ্তির সংখ্যা নির্ধারণ করতে এবং মানগুলিকে একটি ব্যাপ্তিতে ফিট করার জন্য স্কেল করার চেষ্টা করছি। এটি করতে ইচ্ছে করার কারণটি হ'ল আমি জাভা সুইং জাপনেলটিতে উপবৃত্তি আঁকার চেষ্টা করছি। আমি চাই প্রত্যেকটি উপবৃত্তের উচ্চতা এবং প্রস্থ 1-30 বলার পরিসরে থাকুক। আমার কাছে এমন পদ্ধতি রয়েছে যা আমার ডেটা সেট থেকে সর্বনিম্ন এবং সর্বাধিক মান সন্ধান করে তবে রানটাইম পর্যন্ত আমার ন্যূনতম এবং সর্বোচ্চ হবে না have এটি করার কোনও সহজ উপায় আছে?

উত্তর:


507

আসুন আপনি একটি সীমার আকার পরিবর্তন করতে চান বলে [min,max]করতে [a,b]। আপনি সন্তুষ্ট একটি (অবিচ্ছিন্ন) ফাংশন সন্ধান করছেন

f(min) = a
f(max) = b

আপনার ক্ষেত্রে, a1 হবে এবং b30 হবে, তবে আসুন সহজ কিছু দিয়ে শুরু করা যাক এবং [min,max]সীমার মধ্যে ম্যাপ করার চেষ্টা করব [0,1]

ফেলে minএকটি ফাংশন মধ্যে এবং 0 আউট সঙ্গে সম্পন্ন করা যেতে পারে

f(x) = x - min   ===>   f(min) = min - min = 0

সুতরাং এটি আমরা চাই প্রায়। কিন্তু নির্বাণ maxআমাদের দিতে হবে max - min, যখন আমরা আসলে 1. চান সুতরাং আমরা এটা স্কেল করা হয় থাকবে না:

        x - min                                  max - min
f(x) = ---------   ===>   f(min) = 0;  f(max) =  --------- = 1
       max - min                                 max - min

যা আমরা চাই সুতরাং আমাদের একটি অনুবাদ এবং একটি স্কেলিং করা দরকার। এখন এর পরিবর্তে যদি আমরা স্বেচ্ছাচারিত মূল্যবোধ পেতে চাই aএবং bআমাদের আরও কিছু জটিল জটিল প্রয়োজন:

       (b-a)(x - min)
f(x) = --------------  + a
          max - min

আপনি যাচাই করতে পারেন যে এখন রাখার minজন্য xদেয় aএবং maxদেয় b

আপনি লক্ষ্য করতে পারেন যে (b-a)/(max-min)এটি নতুন পরিসরের আকার এবং মূল ব্যাপ্তির আকারের মধ্যে একটি স্কেলিং ফ্যাক্টর। সুতরাং প্রকৃতপক্ষে আমরা প্রথমে অনুবাদ xকরে -min, এটিকে সঠিক ফ্যাক্টারে স্কেলিং করে এবং তারপরে নতুন ন্যূনতম মান পর্যন্ত এটি অনুবাদ করছি a

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


আমি তোমার সাহায্য কে সাধুবাদ জানাই. আমি এমন একটি সমাধান বের করেছি যা নান্দনিকভাবে আনন্দদায়ক দেখার কাজ করে। তবে আমি আরও সঠিক মডেল দেওয়ার জন্য আপনার যুক্তি প্রয়োগ করব। আবারও ধন্যবাদ :)
ব্যবহারকারী 650271

4
কেবলমাত্র একটি অনুস্মারক: মডেলটি আরও সঠিক হয়ে যাবে max != minঅন্যথায় ফাংশনটির ফলাফল
নির্ধারিত নয়

10
এটি কি নিশ্চিত করে যে আমার উদ্ধারকৃত ভেরিয়েবলটি মূল বিতরণটি ধরে রেখেছে?
হাইজেনবার্গ

2
এটি লিনিয়ার স্কেলের একটি দুর্দান্ত বাস্তবায়ন। এটি কি সহজেই লোগারিঘমিক স্কেলে রূপান্তরিত হতে পারে?
tomexx

খুব স্পষ্ট ব্যাখ্যা। minনেতিবাচক এবং maxইতিবাচক হলে এটি কী কাজ করে না, বা উভয়কেই ইতিবাচক হতে হবে?
অ্যান্ড্রু

48

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

function scaleBetween(unscaledNum, minAllowed, maxAllowed, min, max) {
  return (maxAllowed - minAllowed) * (unscaledNum - min) / (max - min) + minAllowed;
}

এর মতো প্রয়োগ হয়েছে, 10-50 এর পরিসীমা 0-100 এর মধ্যে পরিসীমা স্কেল করে।

var unscaledNums = [10, 13, 25, 28, 43, 50];

var maxRange = Math.max.apply(Math, unscaledNums);
var minRange = Math.min.apply(Math, unscaledNums);

for (var i = 0; i < unscaledNums.length; i++) {
  var unscaled = unscaledNums[i];
  var scaled = scaleBetween(unscaled, 0, 100, minRange, maxRange);
  console.log(scaled.toFixed(2));
}

0.00, 18.37, 48.98, 55.10, 85.71, 100.00

সম্পাদনা:

আমি জানি আমি এর উত্তর অনেক দিন আগে দিয়েছি তবে এখানে একটি ক্লিনার ফাংশন যা আমি এখন ব্যবহার করছি:

Array.prototype.scaleBetween = function(scaledMin, scaledMax) {
  var max = Math.max.apply(Math, this);
  var min = Math.min.apply(Math, this);
  return this.map(num => (scaledMax-scaledMin)*(num-min)/(max-min)+scaledMin);
}

এর মতো প্রয়োগ হয়েছে:

[-4, 0, 5, 6, 9].scaleBetween(0, 100);

[0, 30.76923076923077, 69.23076923076923, 76.92307692307692, 100]


var arr = ["-40000.00", "2", "3.000", "4.5825", "0.00008", "1000000000.00008", "0.02008", "100", "- 5000", "- 82.0000048", "0.02" , "0.005", "- 3,0008", "5", "8", "600", "- 1000", "- 5000"]; এই ক্ষেত্রে, আপনার পদ্ধতি অনুসারে, সংখ্যাগুলি খুব কম হচ্ছে। কোনও উপায় আছে কি না, যাতে স্কেলটি (0,100) বা (-100,100) হওয়া উচিত এবং আউটপুটগুলির মধ্যে ফাঁকটি 0.5 (বা যে কোনও সংখ্যা) হওয়া উচিত।

আরআর [] এর জন্যও আমার দৃশ্যের বিষয়টি বিবেচনা করুন।

1
এটি কিছুটা প্রান্তের কেস, তবে অ্যারেতে কেবল একটি মান বা একই মানের একাধিক অনুলিপি থাকলে এটি মারা যায়। সুতরাং [1]। স্কেল বিটিউন (1, 100) এবং [1,1,1]। স্কেল বিটুইন (1,100) উভয়ই এনএএন দিয়ে আউটপুট পূরণ করে।
মালাবার ফ্রন্ট

1
@ মালবারফ্রন্ট, ভাল পর্যবেক্ষণ আমি মনে করি এটির ফলাফলটি হওয়া উচিত কিনা [1, 1, 1], [100, 100, 100]এমনকি এটি অপরিবর্তিত [50.5, 50.5, 50.5]। আপনি এই ক্ষেত্রে রাখতে পারেন:if (max-min == 0) return this.map(num => (scaledMin+scaledMax)/2);
চার্লস ক্লেটন

1
@ চার্লসক্লেটন ফ্যান্টাস্টিক, ধন্যবাদ এটি একটি ট্রিট কাজ করে!
মালবার ফ্রন্ট

27

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

public class Algorithms { 
    public static double scale(final double valueIn, final double baseMin, final double baseMax, final double limitMin, final double limitMax) {
        return ((limitMax - limitMin) * (valueIn - baseMin) / (baseMax - baseMin)) + limitMin;
    }
}

পরীক্ষক:

final double baseMin = 0.0;
final double baseMax = 360.0;
final double limitMin = 90.0;
final double limitMax = 270.0;
double valueIn = 0;
System.out.println(Algorithms.scale(valueIn, baseMin, baseMax, limitMin, limitMax));
valueIn = 360;
System.out.println(Algorithms.scale(valueIn, baseMin, baseMax, limitMin, limitMax));
valueIn = 180;
System.out.println(Algorithms.scale(valueIn, baseMin, baseMax, limitMin, limitMax));

90.0
270.0
180.0

21

আমি এটি কীভাবে বুঝতে পারি তা এখানে:


কত শতাংশ xএকটি পরিসীমা মিথ্যা

ধরে নেওয়া যাক আপনার থেকে শুরু 0করে একটি পরিসীমা রয়েছে 100। এই পরিসীমা থেকে একটি স্বেচ্ছাসেবী নম্বর দেওয়া, যে পরিসীমা থেকে "শতাংশ" এটি থাকা? এটি বেশ সহজ হওয়া উচিত, 0হবে 0%, 50হবে 50%এবং 100হবে 100%

এখন, কি যদি আপনার পরিসীমা ছিল 20থেকে 100? আমরা উপরের মত একই যুক্তি প্রয়োগ করতে পারি না (100 দ্বারা বিভাজন) কারণ:

20 / 100

আমাদের দেয় না 0( এখন 20হওয়া উচিত 0%) এটি ঠিক করার জন্য সহজ হওয়া উচিত, আমাদের কেবল 0ক্ষেত্রে ক্ষেত্রে একটি সংখ্যা তৈরি করা দরকার 20। আমরা এটি বিয়োগ করে করতে পারি:

(20 - 20) / 100

তবে, এটি 100আর কাজ করে না কারণ:

(100 - 20) / 100

আমাদের দেয় না 100%। আবার, আমরা ডিনোমিনেটর থেকে বিয়োগ করে এটিও ঠিক করতে পারি:

(100 - 20) / (100 - 20)

xএকটি পরিসরে কী কী% রয়েছে তার সন্ধানের জন্য আরও সাধারণীকরণ সমীকরণটি হ'ল :

(x - MIN) / (MAX - MIN)

অন্য ব্যাপ্তির স্কেল ব্যাপ্তি

এখন যেহেতু আমরা জানি যে সংখ্যাটি একটি পরিসরে কত শতাংশ থাকে, তাই আমরা এটি অন্য নম্বরটিতে মানচিত্রের জন্য প্রয়োগ করতে পারি। আসুন একটি উদাহরণ দিয়ে যাওয়া যাক।

old range = [200, 1000]
new range = [10, 20]

আমাদের যদি পুরানো পরিসরে একটি নম্বর থাকে তবে নতুন পরিসরে নম্বরটি কী হবে? যাক সংখ্যাটি বলে দিন 400। প্রথমত, 400পুরানো পরিসরের মধ্যে শতাংশটি কী তা নির্ধারণ করুন । আমরা উপরে আমাদের সমীকরণ প্রয়োগ করতে পারেন।

(400 - 200) / (1000 - 200) = 0.25

সুতরাং, 400এই ব্যবস্থার সবচেয়ে গুরত্বপূর্ণ 25%পুরাতন পরিসীমা। আমাদের কেবল 25%নতুন পরিসরের সংখ্যাটি নির্ধারণ করতে হবে। আমার মনে হয় কি 50%এর [0, 20]হয়। এটা 10ঠিক হবে? আপনি কিভাবে এই উত্তর পৌঁছেছেন? ঠিক আছে, আমরা কেবল এটি করতে পারি:

20 * 0.5 = 10

কিন্তু, কি থেকে [10, 20]? 10এখনই আমাদের সবকিছু শিফট করা দরকার । উদাহরণ:

((20 - 10) * 0.5) + 10

আরও সাধারণীকরণের সূত্রটি হ'ল:

((MAX - MIN) * PERCENT) + MIN

কি মূল উদাহরণ 25%কয়েক [10, 20]হল:

((20 - 10) * 0.25) + 10 = 12.5

সুতরাং, 400সীমার মধ্যে [200, 1000]ম্যাপ হবে 12.5সীমার মধ্যে[10, 20]


TLDR

xপুরানো পরিসর থেকে নতুন পরিসীমা মানচিত্র করতে :

OLD PERCENT = (x - OLD MIN) / (OLD MAX - OLD MIN)
NEW X = ((NEW MAX - NEW MIN) * OLD PERCENT) + NEW MIN

1
আমি ঠিক কীভাবে এটি কাজ করেছিলাম। কৌশলযুক্ত অংশটি অনুপাতটি সন্ধান করা যেখানে একটি নম্বর একটি নির্দিষ্ট পরিসরে থাকে। এটি সর্বদা [0, 1] শতাংশের মতোই সীমার মধ্যে হওয়া উচিত, উদাহরণস্বরূপ 0.5% 50% এর জন্য। এরপরে আপনাকে কেবল আপনার প্রয়োজনীয় পরিসরে ফিট করার জন্য এই সংখ্যাটি প্রসারিত / প্রসারিত এবং শিফট করতে হবে।
এসএমইউসামশাহ

খুব সহজ পদ্ধতিতে পদক্ষেপগুলি ব্যাখ্যা করার জন্য আপনাকে ধন্যবাদ - উপরের উত্তর / গুলি কাজগুলি কপিপাস্তে তবে পদক্ষেপগুলি জেনে রাখা কেবল দুর্দান্ত।
রোজএ

11

আমি এই সমাধানটি পেরিয়ে এসেছি তবে এটি আমার প্রয়োজনের সাথে খাপ খায় না। তাই আমি ডি 3 সোর্স কোডটিতে কিছুটা খনন করেছি। আমি ব্যক্তিগতভাবে এটি d3.scale এর মতো করার পরামর্শ দিই।

সুতরাং এখানে আপনি পরিসীমা ডোমেন স্কেল। সুবিধাটি হ'ল আপনি আপনার লক্ষ্য সীমাতে লক্ষণগুলি ফ্লিপ করতে পারেন। কম্পিউটারের স্ক্রিনের y অক্ষগুলি নীচে চলে যায় তাই বড় মানগুলির মধ্যে একটি ছোট y থাকে This

public class Rescale {
    private final double range0,range1,domain0,domain1;

    public Rescale(double domain0, double domain1, double range0, double range1) {
        this.range0 = range0;
        this.range1 = range1;
        this.domain0 = domain0;
        this.domain1 = domain1;
    }

    private double interpolate(double x) {
        return range0 * (1 - x) + range1 * x;
    }

    private double uninterpolate(double x) {
        double b = (domain1 - domain0) != 0 ? domain1 - domain0 : 1 / domain1;
        return (x - domain0) / b;
    }

    public double rescale(double x) {
        return interpolate(uninterpolate(x));
    }
}

এবং এখানে পরীক্ষাটি আপনি দেখতে পাচ্ছেন যেখানে আমি বলতে চাইছি

public class RescaleTest {

    @Test
    public void testRescale() {
        Rescale r;
        r = new Rescale(5,7,0,1);
        Assert.assertTrue(r.rescale(5) == 0);
        Assert.assertTrue(r.rescale(6) == 0.5);
        Assert.assertTrue(r.rescale(7) == 1);

        r = new Rescale(5,7,1,0);
        Assert.assertTrue(r.rescale(5) == 1);
        Assert.assertTrue(r.rescale(6) == 0.5);
        Assert.assertTrue(r.rescale(7) == 0);

        r = new Rescale(-3,3,0,1);
        Assert.assertTrue(r.rescale(-3) == 0);
        Assert.assertTrue(r.rescale(0) == 0.5);
        Assert.assertTrue(r.rescale(3) == 1);

        r = new Rescale(-3,3,-1,1);
        Assert.assertTrue(r.rescale(-3) == -1);
        Assert.assertTrue(r.rescale(0) == 0);
        Assert.assertTrue(r.rescale(3) == 1);
    }
}

"সুবিধাটি হ'ল আপনি আপনার লক্ষ্য সীমাতে চিহ্নগুলি উল্টাতে পারেন।" আমি এটা বুঝতে পারি না। তুমি কি ব্যাখ্যা করতে পারো? আমি আপনার ডি 3-সংস্করণ এবং উপরের সংস্করণ (@ ইরিটেট) থেকে ফিরে আসা মানগুলির পার্থক্য খুঁজে পাচ্ছি না।
nimo23

আপনার লক্ষ্য রেঞ্জটি স্যুইচ করা উদাহরণ 1 এবং 2 এর সাথে তুলনা করুন
KIC

2

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

সুতরাং, x' = (b-a)(x-min)/(max-min) + a(যেখানে খ! = ক) হয়ে যায় x' = x(b-a)/(max-min) + min(-b+a)/(max-min) + aযা আকারে দুই ধাপে কমিয়ে দেওয়া যেতে পারে x' = x*Part1 + Part2

এখানে দুটি কনস্ট্রাক্টর সহ একটি সি # বাস্তবায়ন রয়েছে: একটি প্রশিক্ষণ দেওয়ার জন্য এবং একটি প্রশিক্ষিত উদাহরণ পুনরায় লোড করার জন্য (যেমন, দৃ pers়তা সমর্থন করার জন্য)।

public class MinMaxColumnSpec
{
    /// <summary>
    /// To reduce repetitive computations, the min-max formula has been refactored so that the portions that remain constant are just computed once.
    /// This transforms the forumula from
    /// x' = (b-a)(x-min)/(max-min) + a
    /// into x' = x(b-a)/(max-min) + min(-b+a)/(max-min) + a
    /// which can be further factored into
    /// x' = x*Part1 + Part2
    /// </summary>
    public readonly double Part1, Part2;

    /// <summary>
    /// Use this ctor to train a new scaler.
    /// </summary>
    public MinMaxColumnSpec(double[] columnValues, int newMin = 0, int newMax = 1)
    {
        if (newMax <= newMin)
            throw new ArgumentOutOfRangeException("newMax", "newMax must be greater than newMin");

        var oldMax = columnValues.Max();
        var oldMin = columnValues.Min();

        Part1 = (newMax - newMin) / (oldMax - oldMin);
        Part2 = newMin + (oldMin * (newMin - newMax) / (oldMax - oldMin));
    }

    /// <summary>
    /// Use this ctor for previously-trained scalers with known constants.
    /// </summary>
    public MinMaxColumnSpec(double part1, double part2)
    {
        Part1 = part1;
        Part2 = part2;
    }

    public double Scale(double x) => (x * Part1) + Part2;
}

2

চার্লস ক্লেটনের প্রতিক্রিয়ার ভিত্তিতে আমি কয়েকটি জেএসডোক, ইএস 6 টি টুইটগুলি অন্তর্ভুক্ত করেছি এবং মূল প্রতিক্রিয়ার মন্তব্যগুলি থেকে পরামর্শগুলি অন্তর্ভুক্ত করেছি।

/**
 * Returns a scaled number within its source bounds to the desired target bounds.
 * @param {number} n - Unscaled number
 * @param {number} tMin - Minimum (target) bound to scale to
 * @param {number} tMax - Maximum (target) bound to scale to
 * @param {number} sMin - Minimum (source) bound to scale from
 * @param {number} sMax - Maximum (source) bound to scale from
 * @returns {number} The scaled number within the target bounds.
 */
const scaleBetween = (n, tMin, tMax, sMin, sMax) => {
  return (tMax - tMin) * (n - sMin) / (sMax - sMin) + tMin;
}

if (Array.prototype.scaleBetween === undefined) {
  /**
   * Returns a scaled array of numbers fit to the desired target bounds.
   * @param {number} tMin - Minimum (target) bound to scale to
   * @param {number} tMax - Maximum (target) bound to scale to
   * @returns {number} The scaled array.
   */
  Array.prototype.scaleBetween = function(tMin, tMax) {
    if (arguments.length === 1 || tMax === undefined) {
      tMax = tMin; tMin = 0;
    }
    let sMax = Math.max(...this), sMin = Math.min(...this);
    if (sMax - sMin == 0) return this.map(num => (tMin + tMax) / 2);
    return this.map(num => (tMax - tMin) * (num - sMin) / (sMax - sMin) + tMin);
  }
}

// ================================================================
// Usage
// ================================================================

let nums = [10, 13, 25, 28, 43, 50], tMin = 0, tMax = 100,
    sMin = Math.min(...nums), sMax = Math.max(...nums);

// Result: [ 0.0, 7.50, 37.50, 45.00, 82.50, 100.00 ]
console.log(nums.map(n => scaleBetween(n, tMin, tMax, sMin, sMax).toFixed(2)).join(', '));

// Result: [ 0, 30.769, 69.231, 76.923, 100 ]
console.log([-4, 0, 5, 6, 9].scaleBetween(0, 100).join(', '));

// Result: [ 50, 50, 50 ]
console.log([1, 1, 1].scaleBetween(0, 100).join(', '));
.as-console-wrapper { top: 0; max-height: 100% !important; }

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