public static BagOfWords fit(DataFrame data, Function<String, String[]> tokenizer, int k, String... columns) {
        HashMap<String, Integer> words = new HashMap<>();
        for (var column : columns) {
            for (var text : data.column(column).toStringArray()) {
                for (var word : tokenizer.apply(text)) {
                    words.merge(word, 1, Integer::sum);
                }
            }
        }

        String[] features = new String[words.size()];
        int[] count = new int[words.size()];
        int i = 0;
        for (String word : words.keySet()) {
            features[i] = word;
            count[i++] = -words.get(word);
        }

        QuickSort.sort(count, features);
        return new BagOfWords(columns, tokenizer, Arrays.copyOf(features, Math.min(k, features.length)), false);
    }
@Test
    public void testFit() throws IOException {
        System.out.println("fit");
        try {
            DataFrame data = Read.arff(Paths.getTestData("weka/string.arff"));
            System.out.println(data);

            BagOfWords bag = BagOfWords.fit(data, tokenizer, 10,"LCSH");
            DataFrame df = bag.apply(data);
            System.out.println(df);

            assertEquals(data.nrow(), df.nrow());
            assertEquals(10, df.ncol());
            assertEquals(10, bag.features().length);
            assertEquals("--", bag.features()[0]);
            assertEquals("Union", bag.features()[9]);
            for (int i = 0; i < 10; i++) {
                var feature = bag.features()[i];
                System.out.println(feature);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }