محاسبه توزیع از مجموعه در جاوا

تبدیل مجموعه‌ای از اعداد (یا اشیایی که فیلدهایی هستند که می‌خواهید بررسی کنید) به توزیعی از آن اعداد یک تکنیک آماری رایج است و در زمینه‌های مختلف در گزارش‌گیری و برنامه‌های مبتنی بر داده استفاده می‌شود.

با توجه به مجموعه:

1, 1, 2, 1, 2, 3, 1, 4, 5, 1, 3

می توانید توزیع آنها را به عنوان یک تعداد (فرکانس هر عنصر) بررسی کنید و نتایج را در یک نقشه ذخیره کنید:

{
"1": 5,
"2": 2,
"3": 2,
"4": 1,
"5": 1
}

یا شما می توانید طبیعی کردن مقادیر بر اساس تعداد کل مقادیر - بنابراین آنها را در درصد بیان می کنند:

{
"1": 0.45,
"2": 0.18,
"3": 0.18,
"4": 0.09,
"5": 0.09
}

یا حتی این درصدها را به صورت الف بیان کنید 0..100 فرمت به جای a 0..1 فرمت.

در این راهنما، ما نگاهی به نحوه محاسبه توزیع از یک مجموعه خواهیم داشت - هم با استفاده از انواع اولیه و هم با استفاده از اشیایی که فیلدهایی هستند که ممکن است بخواهید در برنامه خود گزارش دهید.

با اضافه شدن پشتیبانی برنامه نویسی کاربردی در جاوا - محاسبه توزیع ها آسان تر از همیشه است. ما با مجموعه ای از اعداد و مجموعه ای از کار خواهیم کرد Books:

public class Book {

    private String id;
    private String name;
    private String author;
    private long pageNumber;
    private long publishedYear;

   
}

محاسبه توزیع مجموعه در جاوا

بیایید ابتدا نگاهی به نحوه محاسبه توزیع برای انواع اولیه بیاندازیم. کار با اشیاء به سادگی به شما امکان می دهد تا متدهای سفارشی را از کلاس های دامنه خود فراخوانی کنید تا انعطاف پذیری بیشتری در محاسبات ایجاد کنید.

به‌طور پیش‌فرض، درصدها را به صورت دو برابری از نشان می‌دهیم 0.00 به 100.00.

انواع اولیه

بیایید لیستی از اعداد صحیح ایجاد کنیم و توزیع آنها را چاپ کنیم:

List integerList = List.of(1, 1, 2, 1, 2, 3, 1, 4, 5, 1, 3);
System.out.println(calculateIntegerDistribution(integerList));

توزیع به صورت زیر محاسبه می شود:

public static Map calculateIntegerDistribution(List list) {
    return list.stream()
            .collect(Collectors.groupingBy(Integer::intValue,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count * 100.00 / list.size()))))));
}

این روش یک لیست را می پذیرد و آن را استریم می کند. هنگام پخش جریانی، مقادیر هستند گروه بندی شده توسط مقدار صحیح آنها - و مقادیر آنها هستند شمارش با استفاده از Collectors.counting()، قبل از جمع آوری در یک Map که در آن کلیدها مقادیر ورودی و دو برابر درصد آنها را در توزیع نشان می دهند.

روش های کلیدی در اینجا است collect() که می پذیرد دو کلکسیونر. جمع‌آورنده کلید صرفاً با گروه‌بندی مقادیر کلیدی (عناصر ورودی) جمع‌آوری می‌کند. جمع آوری کننده ارزش از طریق collectingAndThen() روشی که به ما اجازه می دهد ارزش ها را بشمار و سپس آنها را در قالب دیگری مانند count * 100.00 / list.size() که به ما اجازه می دهد عناصر شمارش شده را در درصد بیان کنیم:

{1=45.45, 2=18.18, 3=18.18, 4=9.09, 5=9.09}

توزیع را بر اساس مقدار یا کلید مرتب کنید

هنگام ایجاد توزیع - معمولاً می خواهید مقادیر را مرتب کنید. بیشتر اوقات، این اتفاق خواهد افتاد کلید. جاوا HashMaps تضمینی برای حفظ ترتیب درج نیست، بنابراین ما باید از a استفاده کنیم LinkedHashMap که انجام می دهد. به‌علاوه، اکنون که اندازه بسیار کوچک‌تر و قابل کنترل‌تر است، پخش جریانی مجدد نقشه و جمع‌آوری مجدد آن آسان‌تر است.

عملیات قبلی بسته به تعداد کلیدهایی که با آنها سر و کار دارید می‌تواند به سرعت چندین هزار رکورد را در نقشه‌های کوچک جمع کند، بنابراین پخش جریانی مجدد گران نیست:

public static Map calculateIntegerDistribution(List list) {
    return list.stream()
            .collect(Collectors.groupingBy(Integer::intValue,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count.doubleValue() / list.size()))))))
            
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

اشیاء

چگونه می توان این کار را برای اشیا انجام داد؟ همین منطق هم صدق میکنه! به جای یک تابع شناسایی (Integer::intValue)، به جای آن از فیلد مورد نظر استفاده خواهیم کرد – مانند سال انتشار کتاب هایمان. بیایید چند کتاب ایجاد کنیم، آنها را در یک لیست ذخیره کنیم و سپس توزیع سال های انتشار را محاسبه کنیم:

راهنمای عملی و عملی ما برای یادگیری Git را با بهترین روش ها، استانداردهای پذیرفته شده در صنعت و برگه تقلب شامل بررسی کنید. دستورات Google Git را متوقف کنید و در واقع یاد گرفتن آی تی!

Book book1 = new Book("001", "Our Mathematical Universe", "Max Tegmark", 432, 2014);
Book book2 = new Book("002", "Life 3.0", "Max Tegmark", 280, 2017);
Book book3 = new Book("003", "Sapiens", "Yuval Noah Harari", 443, 2011);
Book book4 = new Book("004", "Steve Jobs", "Water Isaacson", 656, 2011);

List books = Arrays.asList(book1, book2, book3, book4);

بیایید توزیع را محاسبه کنیم publishedYear رشته:

public static Map calculateDistribution(List books) {
    return books.stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count * 100.00 / books.size()))))))
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

تنظیم "%.2f" برای تنظیم دقت ممیز شناور این منجر به:

{2011=50.0, 2014=25.0, 2017=25.0}

50% از کتاب های داده شده (2/4) در سال 2011، 25% (1/4) در سال 2014 و 25% (1/4) در سال 2017 منتشر شده است. محدوده در 0..1?

محاسبه توزیع عادی (درصدی) مجموعه در جاوا

برای عادی سازی درصدها از a 0.0...100.0 محدوده تا a 0..1 محدوده - ما به سادگی آن را تطبیق خواهیم داد collectingAndThen() تماس گرفتن نه تعداد را در ضرب کنید 100.0 قبل از تقسیم بر اندازه مجموعه.

پیش از این ، Long تعداد برگردانده شده توسط Collectors.counting() به طور ضمنی به یک دوتایی تبدیل شد (ضرب با مقدار دو برابر) - بنابراین این بار، ما می خواهیم صریحاً doubleValue() از count:

    public static Map calculateDistributionNormalized(List books) {
        return books.stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.4f", count.doubleValue() / books.size()))))))
            
            .entrySet()
            .stream()
            .sorted(comparing(e -> e.getKey()))
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

تنظیم "%.4f" برای تنظیم دقت ممیز شناور این منجر به:

{2011=0.5, 2014=0.25, 2017=0.25}

محاسبه تعداد عناصر (فرکانس) مجموعه

در نهایت - ما می توانیم تعداد عناصر (فرکانس همه عناصر) را در مجموعه به سادگی با تقسیم نکردن تعداد بر اندازه مجموعه بدست آوریم! این یک شمارش کاملاً غیر عادی است:

   public static Map calculateDistributionCount(List books) {
        return books
            .stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Integer.parseInt(String.format("%s", count.intValue()))))))
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

این نتیجه در:

{2011=2, 2014=1, 2017=1}

در واقع، دو کتاب از سال 2011، و یکی از 2014 و 2017 هر کدام وجود دارد.

نتیجه

محاسبه توزیع داده ها یک کار رایج در برنامه های کاربردی غنی از داده است و نیازی به استفاده از کتابخانه های خارجی یا کدهای پیچیده ندارد. با پشتیبانی از برنامه نویسی کاربردی، جاوا کار با مجموعه ها را آسان کرد!

در این پیش نویس کوتاه، نگاهی انداخته ایم به اینکه چگونه می توانید تعداد فرکانس تمام عناصر یک مجموعه را محاسبه کنید، و همچنین نحوه محاسبه نقشه های توزیع نرمال شده به درصد بین 0 و 1 همچنین 0 و 100 در جاوا

تمبر زمان:

بیشتر از Stackabuse