File Coverage

blib/lib/Rstats/Func.pm
Criterion Covered Total %
statement 1962 2076 94.5
branch 657 802 81.9
condition 101 137 73.7
subroutine 133 137 97.0
pod 0 121 0.0
total 2853 3273 87.1


line stmt bran cond sub pod time code
1             package Rstats::Func;
2              
3 21     21   103 use strict;
  21         38  
  21         575  
4 21     21   102 use warnings;
  21         36  
  21         698  
5              
6             require Rstats;
7              
8 21     21   107 use Carp 'croak';
  21         49  
  21         940  
9 21     21   126 use Rstats::Func;
  21         47  
  21         556  
10 21     21   95 use Rstats::Util;
  21         34  
  21         533  
11 21     21   16855 use Text::UnicodeTable::Simple;
  21         847919  
  21         937  
12              
13 21     21   267 use List::Util ();
  21         37  
  21         335  
14 21     21   17623 use POSIX ();
  21         135532  
  21         698  
15 21     21   14927 use Math::Round ();
  21         22701  
  21         394  
16 21     21   17907 use Encode ();
  21         238992  
  21         524061  
17              
18             sub factor {
19 86     86 0 142 my $r = shift;
20            
21 86         414 my ($x1, $x_levels, $x_labels, $x_exclude, $x_ordered)
22             = args_array($r, [qw/x levels labels exclude ordered/], @_);
23              
24             # default - x
25 86 100       920 $x1 = Rstats::Func::as_character($r, $x1) unless Rstats::Func::is_character($r, $x1);
26            
27             # default - levels
28 86 100       489 unless (defined $x_levels) {
29 72         209 $x_levels = Rstats::Func::sort($r, unique($r, $x1), {'na.last' => Rstats::Func::TRUE($r)});
30             }
31            
32             # default - exclude
33 86 100       1960 $x_exclude = NA($r) unless defined $x_exclude;
34            
35             # fix levels
36 86 100 66     462 if (defined $x_exclude->value && Rstats::Func::length($r, $x_exclude)->value) {
37 1         3 my $new_a_levels_values = [];
38 1         3 for my $x_levels_value (@{$x_levels->values}) {
  1         8  
39 3         4 my $match;
40 3         4 for my $x_exclude_value (@{$x_exclude->values}) {
  3         17  
41 3 100 33     35 if (defined $x_levels_value
      66        
42             && defined $x_exclude_value
43             && $x_levels_value eq $x_exclude_value)
44             {
45 1         2 $match = 1;
46 1         3 last;
47             }
48             }
49 3 100       13 push @$new_a_levels_values, $x_levels_value unless $match;
50             }
51 1         33 $x_levels = Rstats::Func::c_($r, @$new_a_levels_values);
52             }
53            
54             # default - labels
55 86 100       257 unless (defined $x_labels) {
56 79         111 $x_labels = $x_levels;
57             }
58            
59             # default - ordered
60 86 100       1420 $x_ordered = Rstats::Func::is_ordered($r, $x1) unless defined $x_ordered;
61            
62 86         809 my $x1_values = $x1->values;
63            
64 86         1050 my $labels_length = Rstats::Func::length($r, $x_labels)->value;
65 86         1122 my $levels_length = Rstats::Func::length($r, $x_levels)->value;
66 86 100 100     678 if ($labels_length == 1 && Rstats::Func::get_length($r, $x1) != 1) {
    50          
67 1         7 my $value = $x_labels->value;
68 1         10 $x_labels = paste($r, $value, C_($r, "1:$levels_length"), {sep => ""});
69             }
70             elsif ($labels_length != $levels_length) {
71 0         0 Carp::croak("Error in factor 'labels'; length $labels_length should be 1 or $levels_length");
72             }
73            
74             # Levels hash
75 86         118 my $levels;
76 86         435 my $x_levels_values = $x_levels->values;
77 86         290 for (my $i = 1; $i <= $levels_length; $i++) {
78 217         378 my $x_levels_value = $x_levels_values->[$i - 1];
79 217         698 $levels->{$x_levels_value} = $i;
80             }
81            
82 86         145 my $f1_values = [];
83 86         188 for my $x1_value (@$x1_values) {
84 347 100       596 if (!defined $x1_value) {
85 1         4 push @$f1_values, undef;
86             }
87             else {
88             my $f1_value = exists $levels->{$x1_value}
89 346 100       710 ? $levels->{$x1_value}
90             : undef;
91 346         619 push @$f1_values, $f1_value;
92             }
93             }
94            
95 86         1057 my $f1 = Rstats::Func::c_integer($r, @$f1_values);
96 86 100       349 if ($x_ordered) {
97 7         83 $f1->{class} = Rstats::Func::c_character($r, 'factor', 'ordered');
98             }
99             else {
100 79         834 $f1->{class} = Rstats::Func::c_character($r, 'factor');
101             }
102 86         863 $f1->{levels} = Rstats::Func::as_vector($r, $x_labels);
103            
104 86         194 $f1->{type} = 'integer';
105 86         135 $f1->{object_type} = 'array';
106            
107 86         1216 return $f1;
108             }
109              
110             sub ordered {
111 4     4 0 8 my $r = shift;
112            
113 4 100       19 my $opt = ref $_[-1] eq 'HASH' ? pop : {};
114 4         29 $opt->{ordered} = Rstats::Func::TRUE($r);
115            
116 4         14 factor($r, @_, $opt);
117             }
118              
119             sub list {
120 90     90 0 149 my $r = shift;
121            
122 90         202 my @elements = @_;
123            
124 90 100       157 @elements = map { !Rstats::Func::is_list($r, $_) ? Rstats::Func::to_object($r, $_) : $_ } @elements;
  181         1631  
125            
126 90         499 my $list = Rstats::Func::new_list($r);
127 90         2063 $list->list(\@elements);
128 90         2252 $list->r($r);
129            
130 90         645 return $list;
131             }
132              
133             sub data_frame {
134 45     45 0 83 my $r = shift;
135            
136 45         150 my @data = @_;
137            
138 45 100 66     170 return cbind($r, @data) if ref $data[0] && Rstats::Func::is_data_frame($r, $data[0]);
139            
140 44         80 my $elements = [];
141            
142             # name count
143 44         120 my $name_count = {};
144            
145             # count
146 44         68 my $counts = [];
147 44         64 my $column_names = [];
148 44         82 my $row_names = [];
149 44         66 my $row_count = 1;
150 44         167 while (my ($name, $v) = splice(@data, 0, 2)) {
151 113 100 100     1015 if (Rstats::Func::is_character($r, $v) && !grep {$_ eq 'AsIs'} @{$v->class->values}) {
  34         204  
  34         176  
152 31         82 $v = Rstats::Func::as_factor($r, $v);
153             }
154              
155 113         1541 my $dim_values = Rstats::Func::dim($r, $v)->values;
156 113 50       394 if (@$dim_values > 1) {
157 0         0 my $count = $dim_values->[0];
158 0         0 my $dim_product = 1;
159 0         0 $dim_product *= $dim_values->[$_] for (1 .. @$dim_values - 1);
160            
161 0         0 for my $num (1 .. $dim_product) {
162 0         0 push @$counts, $count;
163 0         0 my $fix_name;
164 0 0       0 if (my $count = $name_count->{$name}) {
165 0         0 $fix_name = "$name.$count";
166             }
167             else {
168 0         0 $fix_name = $name;
169             }
170 0         0 push @$column_names, $fix_name;
171 0         0 push @$elements, splice(@{$v->values}, 0, $count);
  0         0  
172             }
173             }
174             else {
175 113         512 my $count = Rstats::Func::get_length($r, $v);
176 113         194 push @$counts, $count;
177 113         123 my $fix_name;
178 113 100       253 if (my $count = $name_count->{$name}) {
179 2         6 $fix_name = "$name.$count";
180             }
181             else {
182 111         170 $fix_name = $name;
183             }
184 113         198 push @$column_names, $fix_name;
185 113         209 push @$elements, $v;
186             }
187 113         226 push @$row_names, "$row_count";
188 113         141 $row_count++;
189 113         717 $name_count->{$name}++;
190             }
191            
192             # Max count
193 44         132 my $max_count = List::Util::max @$counts;
194            
195             # Check multiple number
196 44         95 for my $count (@$counts) {
197 113 50       314 if ($max_count % $count != 0) {
198 0         0 Carp::croak "Error in data.frame: arguments imply differing number of rows: @$counts";
199             }
200             }
201            
202             # Fill vector
203 44         138 for (my $i = 0; $i < @$counts; $i++) {
204 113         147 my $count = $counts->[$i];
205            
206 113         167 my $repeat = $max_count / $count;
207 113 100       392 if ($repeat > 1) {
208 1         2 my $repeat_elements = [];
209 1         7 push @$repeat_elements, $elements->[$i] for (1 .. $repeat);
210 1         30 $elements->[$i] = Rstats::Func::c_($r, @$repeat_elements);
211             }
212             }
213            
214             # Create data frame
215 44         261 my $data_frame = Rstats::Func::new_data_frame($r);
216 44         102 $data_frame->{row_length} = $max_count;
217 44         1036 $data_frame->list($elements);
218 44         2531 Rstats::Func::dimnames(
219             $r,
220             $data_frame,
221             Rstats::Func::list(
222             $r,
223             Rstats::Func::c_($r, @$row_names),
224             Rstats::Func::c_($r, @$column_names)
225             )
226             );
227 44         1826 $data_frame->r($r);
228            
229 44         388 return $data_frame;
230             }
231              
232             sub matrix {
233 75     75 0 133 my $r = shift;
234            
235            
236 75         351 my ($x1, $x_nrow, $x_ncol, $x_byrow, $x_dirnames)
237             = Rstats::Func::args_array($r, ['x1', 'nrow', 'ncol', 'byrow', 'dirnames'], @_);
238              
239 75 50       266 Carp::croak "matrix method need data as frist argument"
240             unless defined $x1;
241            
242             # Row count
243 75         103 my $nrow;
244 75 100       491 $nrow = $x_nrow->value if defined $x_nrow;
245            
246             # Column count
247 75         145 my $ncol;
248 75 100       439 $ncol = $x_ncol->value if defined $x_ncol;
249            
250             # By row
251 75         168 my $byrow;
252 75 100       206 $byrow = $x_byrow->value if defined $x_byrow;
253            
254 75         407 my $x1_values = $x1->values;
255 75         368 my $x1_length = Rstats::Func::get_length($r, $x1);
256 75 100 100     448 if (!defined $nrow && !defined $ncol) {
    100          
    100          
257 9         18 $nrow = $x1_length;
258 9         13 $ncol = 1;
259             }
260             elsif (!defined $nrow) {
261 1         3 $nrow = int($x1_length / $ncol);
262 1   50     4 $nrow ||= 1;
263             }
264             elsif (!defined $ncol) {
265 3         10 $ncol = int($x1_length / $nrow);
266 3   100     16 $ncol ||= 1;
267             }
268 75         146 my $length = $nrow * $ncol;
269            
270 75         169 my $dim = [$nrow, $ncol];
271 75         114 my $matrix;
272             my $x_matrix;
273              
274 75 50       732 if (Rstats::Func::get_type($r, $x1) eq "character") {
    50          
    100          
    50          
    50          
275 0         0 $x_matrix = c_character($r, $x1_values);
276             }
277             elsif (Rstats::Func::get_type($r, $x1) eq "complex") {
278 0         0 $x_matrix = c_complex($r, $x1_values);
279             }
280             elsif (Rstats::Func::get_type($r, $x1) eq "double") {
281 70         1686 $x_matrix = c_double($r, $x1_values);
282             }
283             elsif (Rstats::Func::get_type($r, $x1) eq "integer") {
284 0         0 $x_matrix = c_integer($r, $x1_values);
285             }
286             elsif (Rstats::Func::get_type($r, $x1) eq "logical") {
287 5         43 $x_matrix = c_logical($r, $x1_values);
288             }
289             else {
290 0         0 croak("Invalid type " . Rstats::Func::get_type($r, $x1) . " is passed");
291             }
292            
293 75 100       200 if ($byrow) {
294 1         161 $matrix = Rstats::Func::array(
295             $r,
296             $x_matrix,
297             Rstats::Func::c_($r, $dim->[1], $dim->[0]),
298             );
299            
300 1         35 $matrix = Rstats::Func::t($r, $matrix);
301             }
302             else {
303 74         9385 $matrix = Rstats::Func::array($r, $x_matrix, Rstats::Func::c_($r, @$dim));
304             }
305            
306 75         2724 return $matrix;
307             }
308              
309              
310              
311              
312             sub dimnames {
313 61     61 0 100 my $r = shift;
314            
315 61         104 my $x1 = shift;
316            
317 61 100       148 if (@_) {
318 46         64 my $dimnames_list = shift;
319 46 50       133 if ($dimnames_list->{object_type} eq 'list') {
320 46         207 my $length = Rstats::Func::get_length($r, $dimnames_list);
321 46         78 my $dimnames = [];
322 46         146 for (my $i = 0; $i < $length; $i++) {
323 92         525 my $x_dimname = $dimnames_list->getin($i + 1);
324 92 50       842 if (is_character($r, $x_dimname)) {
325 92         763 my $dimname = Rstats::Func::as_vector($r, $x_dimname);
326 92         683 push @$dimnames, $dimname;
327             }
328             else {
329 0         0 croak "dimnames must be character list";
330             }
331             }
332 46         111 $x1->{dimnames} = $dimnames;
333            
334 46 100       402 if (Rstats::Func::is_data_frame($r, $x1)) {
335 44         486 $x1->{names} = Rstats::Func::as_vector($r, $x1->{dimnames}[1]);
336             }
337             }
338             else {
339 0         0 croak "dimnames must be list";
340             }
341             }
342             else {
343 15 100       64 if (exists $x1->{dimnames}) {
344 5         15 my $x_dimnames = Rstats::Func::list($r);
345 5         113 $x_dimnames->list($x1->{dimnames});
346             }
347             else {
348 10         59 return Rstats::Func::NULL($r);
349             }
350             }
351             }
352              
353             sub rownames {
354 19     19 0 32 my $r = shift;
355            
356 19         32 my $x1 = shift;
357            
358 19 100       49 if (@_) {
359 3         10 my $x_rownames = Rstats::Func::to_object($r, shift);
360            
361 3 100       13 unless (exists $x1->{dimnames}) {
362 1         4 $x1->{dimnames} = [];
363             }
364            
365 3         34 $x1->{dimnames}[0] = Rstats::Func::as_vector($r, $x_rownames);
366             }
367             else {
368 16         112 my $x_rownames = Rstats::Func::NULL($r);
369 16 100       84 if (defined $x1->{dimnames}[0]) {
370 10         108 $x_rownames = Rstats::Func::as_vector($r, $x1->{dimnames}[0]);
371             }
372 16         124 return $x_rownames;
373             }
374             }
375              
376              
377             sub colnames {
378 18     18 0 29 my $r = shift;
379            
380 18         40 my $x1 = shift;
381            
382 18 100       47 if (@_) {
383 3         10 my $x_colnames = Rstats::Func::to_object($r, shift);
384            
385 3 100       11 unless (exists $x1->{dimnames}) {
386 2         5 $x1->{dimnames} = [];
387             }
388            
389 3         37 $x1->{dimnames}[1] = Rstats::Func::as_vector($r, $x_colnames);
390             }
391             else {
392 15         86 my $x_colnames = Rstats::Func::NULL($r);
393 15 100       57 if (defined $x1->{dimnames}[1]) {
394 9         99 $x_colnames = Rstats::Func::as_vector($r, $x1->{dimnames}[1]);
395             }
396 15         215 return $x_colnames;
397             }
398             }
399              
400             sub labels {
401 1     1 0 3 my $r = shift;
402 1         8 return $r->as->character(@_);
403             }
404              
405             sub as_list {
406 2     2 0 4 my $r = shift;
407            
408 2         4 my $x1 = shift;
409            
410 2 100       7 if (exists $x1->{list}) {
411 1         3 return $x1;
412             }
413             else {
414 1         7 my $list = Rstats::Func::new_list($r);;
415 1         11 my $x2 = Rstats::Func::as_vector($r, $x1);
416 1         24 $list->list([$x2]);
417            
418 1         7 return $list;
419             }
420             }
421              
422             sub as_factor {
423 43     43 0 56 my $r = shift;
424            
425 43         63 my $x1 = shift;
426            
427 43 100       771 if (Rstats::Func::is_factor($r, $x1)) {
428 11         87 return $x1;
429             }
430             else {
431 32 50       268 my $a = is_character($r, $x1) ? $x1 : Rstats::Func::as_character($r, $x1);
432 32         191 my $f = Rstats::Func::factor($r, $a);
433            
434 32         89 return $f;
435             }
436             }
437              
438             sub as_matrix {
439 14     14 0 24 my $r = shift;
440            
441 14         22 my $x1 = shift;
442            
443 14         80 my $x1_dim_elements = $x1->dim_as_array->values;
444 14         78 my $x1_dim_count = @$x1_dim_elements;
445 14         29 my $x2_dim_elements = [];
446 14         25 my $row;
447             my $col;
448 14 100       37 if ($x1_dim_count == 2) {
449 4         11 $row = $x1_dim_elements->[0];
450 4         9 $col = $x1_dim_elements->[1];
451             }
452             else {
453 10         15 $row = 1;
454 10         59 $row *= $_ for @$x1_dim_elements;
455 10         15 $col = 1;
456             }
457            
458 14         145 my $x2 = Rstats::Func::as_vector($r, $x1);
459            
460 14         53 return Rstats::Func::matrix($r, $x2, $row, $col);
461             }
462              
463             sub I {
464 3     3 0 6 my $r = shift;
465            
466 3         5 my $x1 = shift;
467            
468 3         42 my $x2 = Rstats::Func::c_($r, $x1);
469 3         21 Rstats::Func::copy_attrs_to($r, $x1, $x2);
470 3         16 $x2->class('AsIs');
471            
472 3         19 return $x2;
473             }
474              
475             sub subset {
476 2     2 0 4 my $r = shift;
477            
478 2         11 my ($x1, $x_condition, $x_names)
479             = args_array($r, ['x1', 'condition', 'names'], @_);
480            
481 2 100       13 $x_names = Rstats::Func::NULL($r) unless defined $x_names;
482            
483 2         13 my $x2 = $x1->get($x_condition, $x_names);
484            
485 2         10 return $x2;
486             }
487              
488             sub t {
489 5     5 0 9 my $r = shift;
490            
491 5         8 my $x1 = shift;
492            
493 5         61 my $x1_row = Rstats::Func::dim($r, $x1)->values->[0];
494 5         81 my $x1_col = Rstats::Func::dim($r, $x1)->values->[1];
495            
496 5         35 my $x2 = matrix($r, 0, $x1_col, $x1_row);
497            
498 5         15 for my $row (1 .. $x1_row) {
499 17         37 for my $col (1 .. $x1_col) {
500 36         198 my $value = $x1->value($row, $col);
501 36         208 $x2->at($col, $row);
502 36         80 Rstats::Func::set($r, $x2, $value);
503             }
504             }
505            
506 5         21 return $x2;
507             }
508              
509             sub transform {
510 2     2 0 4 my $r = shift;
511            
512 2         3 my $x1 = shift;
513 2         6 my @args = @_;
514              
515 2         25 my $new_names = Rstats::Func::names($r, $x1)->values;
516 2         52 my $new_elements = $x1->list;
517            
518 2         32 my $names = Rstats::Func::names($r, $x1)->values;
519            
520 2         16 while (my ($new_name, $new_v) = splice(@args, 0, 2)) {
521 3 100       26 if (Rstats::Func::is_character($r, $new_v)) {
522 2         9 $new_v = Rstats::Func::I($r, $new_v);
523             }
524              
525 3         12 my $found_pos = -1;
526 3         9 for (my $i = 0; $i < @$names; $i++) {
527 5         9 my $name = $names->[$i];
528 5 100       15 if ($new_name eq $name) {
529 2         2 $found_pos = $i;
530 2         5 last;
531             }
532             }
533            
534 3 100       74 if ($found_pos == -1) {
535 1         3 push @$new_names, $new_name;
536 1         5 push @$new_elements, $new_v;
537             }
538             else {
539 2         23 $new_elements->[$found_pos] = $new_v;
540             }
541             }
542            
543            
544 2         4 my @new_args;
545 2         7 for (my $i = 0; $i < @$new_names; $i++) {
546 7         21 push @new_args, $new_names->[$i], $new_elements->[$i];
547             }
548            
549 2         7 my $x2 = Rstats::Func::data_frame($r, @new_args);
550            
551 2         12 return $x2;
552             }
553              
554             sub na_omit {
555 1     1 0 3 my $r = shift;
556            
557 1         2 my $x1 = shift;
558            
559 1         2 my @poss;
560 1         2 for my $v (@{$x1->list}) {
  1         23  
561 3         18 for (my $index = 1; $index <= $x1->{row_length}; $index++) {
562 9 100       42 push @poss, $index unless defined $v->value($index);
563             }
564             }
565            
566 1         28 my $x2 = $x1->get(-c_($r, @poss), NULL($r));
567            
568 1         14 return $x2;
569             }
570              
571             # TODO: merge is not implemented yet
572             sub merge {
573 0     0 0 0 my $r = shift;
574              
575 0         0 die "Error in merge() : merge is not implemented yet";
576            
577 0         0 my ($x1, $x2, $x_all, $x_all_x, $x_all_y, $x_by, $x_by_x, $x_by_y, $x_sort)
578             = args_array($r, [qw/x1 x2 all all.x all.y by by.x by.y sort/], @_);
579            
580             # Join way
581 0 0       0 $x_all = Rstats::Func::FALSE($r) unless defined $x_all;
582 0 0       0 $x_all_x = Rstats::Func::FALSE($r) unless defined $x_all_x;
583 0 0       0 $x_all_y = Rstats::Func::FALSE($r) unless defined $x_all_y;
584 0         0 my $all;
585 0 0       0 if ($x_all) {
    0          
    0          
586 0         0 $all = 'both';
587             }
588             elsif ($x_all_x) {
589 0         0 $all = 'left';
590             }
591             elsif ($x_all_y) {
592 0         0 $all = 'rigth';
593             }
594             else {
595 0         0 $all = 'common';
596             }
597            
598             # ID
599 0 0       0 $x_by = Rstats::Func::names($r, $x1)->get(1) unless defined $x_by;
600 0 0       0 $x_by_x = $x_by unless defined $x_by_x;
601 0 0       0 $x_by_y = $x_by unless defined $x_by_y;
602 0         0 my $by_x = $x_by_x->value;
603 0         0 my $by_y = $x_by_y->value;
604            
605             # Sort
606 0 0       0 my $sort = defined $x_sort ? $x_sort->value : 0;
607             }
608              
609             my $type_level = {
610             character => 6,
611             complex => 5,
612             double => 4,
613             integer => 3,
614             logical => 2,
615             na => 1
616             };
617              
618             sub higher_type {
619 37     37 0 50 my $r = shift;
620            
621 37         49 my ($type1, $type2) = @_;
622            
623 37 100       90 if ($type_level->{$type1} > $type_level->{$type2}) {
624 4         14 return $type1;
625             }
626             else {
627 33         159 return $type2;
628             }
629             }
630              
631             # TODO
632             #read.table(file, header = FALSE, sep = "", quote = "\"'",
633             # dec = ".", row.names, col.names,
634             # as.is = !stringsAsFactors,
635             # na.strings = "NA", colClasses = NA, nrows = -1,
636             # skip = 0, check.names = TRUE, fill = !blank.lines.skip,
637             # strip.white = FALSE, blank.lines.skip = TRUE,
638             # comment.char = "#",
639             # allowEscapes = FALSE, flush = FALSE,
640             # stringsAsFactors = default.stringsAsFactors(),
641             # encoding = "unknown")
642             sub read_table {
643 4     4 0 6 my $r = shift;
644            
645 4         21 my ($x_file, $x_sep, $x_skip, $x_nrows, $x_header, $x_comment_char, $x_row_names, $x_encoding)
646             = args_array($r, [qw/file sep skip nrows header comment.char row.names encoding/], @_);
647            
648 4         29 my $file = $x_file->value;
649 4 50       231 open(my $fh, '<', $file)
650             or Carp::croak "cannot open file '$file': $!";
651            
652             # Separater
653 4 100       17 my $sep = defined $x_sep ? $x_sep->value : "\\s+";
654 4 50       14 my $encoding = defined $x_encoding ? $x_encoding->value : 'UTF-8';
655 4 100       22 my $skip = defined $x_skip ? $x_skip->value : 0;
656 4 100       15 my $header_opt = defined $x_header ? $x_header->value : 0;
657            
658 4         7 my $type_columns;
659 4         6 my $columns = [];
660 4         8 my $row_size;
661             my $header;
662 4         78 while (my $line = <$fh>) {
663 14 100       28 if ($skip > 0) {
664 2         4 $skip--;
665 2         6 next;
666             }
667 12         36 $line = Encode::decode($encoding, $line);
668 12         703 $line =~ s/\x0D?\x0A?$//;
669            
670 12 100 100     44 if ($header_opt && !$header) {
671 1         13 $header = [split(/$sep/, $line)];
672 1         5 next;
673             }
674            
675 11         79 my @row = split(/$sep/, $line);
676 11         16 my $current_row_size = @row;
677 11   66     32 $row_size ||= $current_row_size;
678            
679             # Row size different
680 11 50       26 Carp::croak "line $. did not have $row_size elements"
681             if $current_row_size != $row_size;
682            
683 11   100     35 $type_columns ||= [('logical') x $row_size];
684            
685 11         29 for (my $i = 0; $i < @row; $i++) {
686            
687 37   100     95 $columns->[$i] ||= [];
688 37         45 push @{$columns->[$i]}, $row[$i];
  37         84  
689 37         41 my $type;
690 37 100       408 if (defined Rstats::Util::looks_like_na($row[$i])) {
    100          
    100          
    100          
    100          
691 5         6 $type = 'logical';
692             }
693             elsif (defined Rstats::Util::looks_like_logical($row[$i])) {
694 4         7 $type = 'logical';
695             }
696             elsif (defined Rstats::Util::looks_like_integer($row[$i])) {
697 10         19 $type = 'integer';
698             }
699             elsif (defined Rstats::Util::looks_like_double($row[$i])) {
700 10         13 $type = 'double';
701             }
702             elsif (defined Rstats::Util::looks_like_complex($row[$i])) {
703 4         6 $type = 'complex';
704             }
705             else {
706 4         5 $type = 'character';
707             }
708 37         90 $type_columns->[$i] = Rstats::Func::higher_type($r, $type_columns->[$i], $type);
709             }
710             }
711            
712 4         8 my $data_frame_args = [];
713 4         13 for (my $i = 0; $i < $row_size; $i++) {
714 11 100       31 if (defined $header->[$i]) {
715 2         5 push @$data_frame_args, $header->[$i];
716             }
717             else {
718 9         26 push @$data_frame_args, "V" . ($i + 1);
719             }
720 11         16 my $type = $type_columns->[$i];
721 11 100       43 if ($type eq 'character') {
    100          
    100          
    100          
722 1         2 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  1         56  
723 1         16 push @$data_frame_args, Rstats::Func::as_factor($r, $x1);
724             }
725             elsif ($type eq 'complex') {
726 1         2 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  1         42  
727 1         166 push @$data_frame_args, Rstats::Func::as_complex($r, $x1);
728             }
729             elsif ($type eq 'double') {
730 4         7 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  4         139  
731 4         210 push @$data_frame_args, Rstats::Func::as_double($r, Rstats::Func::as_double($r, $x1));
732             }
733             elsif ($type eq 'integer') {
734 4         8 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  4         119  
735 4         207 push @$data_frame_args, Rstats::Func::as_integer($r, $x1);
736             }
737             else {
738 1         2 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  1         42  
739 1         57 push @$data_frame_args, Rstats::Func::as_logical($r, $x1);
740             }
741             }
742            
743 4         13 my $d1 = Rstats::Func::data_frame($r, @$data_frame_args);
744            
745 4         161 return $d1;
746             }
747              
748             sub interaction {
749 5     5 0 11 my $r = shift;
750            
751 5         6 my $opt;
752 5 100       18 $opt = ref $_[-1] eq 'HASH' ? pop : {};
753 5         9 my @xs = map { Rstats::Func::as_factor($r, to_object($r, $_)) } @_;
  11         57  
754 5         10 my ($x_drop, $x_sep);
755 5         19 ($x_drop, $x_sep) = args_array($r, ['drop', 'sep'], $opt);
756            
757 5 100       81 $x_sep = Rstats::Func::c_($r, ".") unless defined $x_sep;
758 5         42 my $sep = $x_sep->value;
759            
760 5 100       38 $x_drop = Rstats::Func::FALSE($r) unless defined $x_drop;
761            
762 5         9 my $max_length;
763 5         9 my $values_list = [];
764 5         12 for my $x (@xs) {
765 11         129 my $length = Rstats::Func::length($r, $x)->value;
766 11 100 66     85 $max_length = $length if !defined $max_length || $length > $max_length;
767             }
768            
769             # Vector
770 5         8 my $f1_elements = [];
771 5         17 for (my $i = 0; $i < $max_length; $i++) {
772 18         23 my $chars = [];
773 18         34 for my $x (@xs) {
774 39         2008 my $fix_x = Rstats::Func::as_character($r, $x);
775 39         584 my $length = Rstats::Func::get_length($r, $fix_x);
776 39         227 push @$chars, $fix_x->value(($i % $length) + 1)
777             }
778 18         44 my $value = join $sep, @$chars;
779 18         67 push @$f1_elements, $value;
780             }
781            
782             # Levels
783 5         6 my $f1;
784 5         10 my $f1_levels_elements = [];
785 5 100       16 if ($x_drop) {
786 1         2 $f1_levels_elements = $f1_elements;
787 1         37 $f1 = factor($r, c_($r, @$f1_elements));
788             }
789             else {
790 4         8 my $levels = [];
791 4         9 for my $x (@xs) {
792 9         107 push @$levels, Rstats::Func::levels($r, $x)->values;
793             }
794 4         57 my $cps = Rstats::Util::cross_product($levels);
795 4         14 for my $cp (@$cps) {
796 20         39 my $value = join $sep, @$cp;
797 20         31 push @$f1_levels_elements, $value;
798             }
799 4         14 $f1_levels_elements = [sort {$a cmp $b} @$f1_levels_elements];
  32         48  
800 4         337 $f1 = factor($r, c_($r, @$f1_elements), {levels => Rstats::Func::c_($r, @$f1_levels_elements)});
801             }
802            
803 5         137 return $f1;
804             }
805              
806             sub gl {
807 5     5 0 6 my $r = shift;
808            
809 5         22 my ($x_n, $x_k, $x_length, $x_labels, $x_ordered)
810             = args_array($r, [qw/n k length labels ordered/], @_);
811            
812 5         36 my $n = $x_n->value;
813 5         28 my $k = $x_k->value;
814 5 100       65 $x_length = Rstats::Func::c_($r, $n * $k) unless defined $x_length;
815 5         36 my $length = $x_length->value;
816            
817 5         145 my $x_levels = Rstats::Func::c_($r, 1 .. $n);
818 5         141 $x_levels = Rstats::Func::as_character($r, $x_levels);
819 5         45 my $levels = $x_levels->values;
820            
821 5         10 my $x1_elements = [];
822 5         18 my $level = 1;
823 5         6 my $j = 1;
824 5         18 for (my $i = 0; $i < $length; $i++) {
825 47 100       88 if ($j > $k) {
826 13         17 $j = 1;
827 13         16 $level++;
828             }
829 47 100       92 if ($level > @$levels) {
830 3         5 $level = 1;
831             }
832 47         84 push @$x1_elements, $level;
833 47         111 $j++;
834             }
835            
836 5         408 my $x1 = Rstats::Func::c_($r, @$x1_elements);
837            
838 5 100       97 $x_labels = $x_levels unless defined $x_labels;
839 5 100       33 $x_ordered = Rstats::Func::FALSE($r) unless defined $x_ordered;
840            
841 5         22 return factor($r, $x1, {levels => $x_levels, labels => $x_labels, ordered => $x_ordered});
842             }
843              
844             sub upper_tri {
845 2     2 0 5 my $r = shift;
846            
847 2         8 my ($x1_m, $x1_diag) = args_array($r, ['m', 'diag'], @_);
848            
849 2 100       13 my $diag = defined $x1_diag ? $x1_diag->value : 0;
850            
851 2         4 my $x2_values = [];
852 2 50       37 if (Rstats::Func::is_matrix($r, $x1_m)) {
853 2         28 my $x1_dim_values = Rstats::Func::dim($r, $x1_m)->values;
854 2         10 my $rows_count = $x1_dim_values->[0];
855 2         4 my $cols_count = $x1_dim_values->[1];
856            
857 2         8 for (my $col = 0; $col < $cols_count; $col++) {
858 8         18 for (my $row = 0; $row < $rows_count; $row++) {
859 24         25 my $x2_value;
860 24 100       38 if ($diag) {
861 12 100       23 $x2_value = $col >= $row ? 1 : 0;
862             }
863             else {
864 12 100       22 $x2_value = $col > $row ? 1 : 0;
865             }
866 24         64 push @$x2_values, $x2_value;
867             }
868             }
869            
870 2         26 my $x2 = matrix($r, Rstats::Func::c_logical($r, @$x2_values), $rows_count, $cols_count);
871            
872 2         17 return $x2;
873             }
874             else {
875 0         0 Carp::croak 'Error in upper_tri() : Not implemented';
876             }
877             }
878              
879             sub lower_tri {
880 2     2 0 5 my $r = shift;
881            
882 2         7 my ($x1_m, $x1_diag) = args_array($r, ['m', 'diag'], @_);
883            
884 2 100       13 my $diag = defined $x1_diag ? $x1_diag->value : 0;
885            
886 2         4 my $x2_values = [];
887 2 50       32 if (Rstats::Func::is_matrix($r, $x1_m)) {
888 2         25 my $x1_dim_values = Rstats::Func::dim($r, $x1_m)->values;
889 2         10 my $rows_count = $x1_dim_values->[0];
890 2         5 my $cols_count = $x1_dim_values->[1];
891            
892 2         8 for (my $col = 0; $col < $cols_count; $col++) {
893 8         20 for (my $row = 0; $row < $rows_count; $row++) {
894 24         30 my $x2_value;
895 24 100       34 if ($diag) {
896 12 100       28 $x2_value = $col <= $row ? 1 : 0;
897             }
898             else {
899 12 100       35 $x2_value = $col < $row ? 1 : 0;
900             }
901 24         66 push @$x2_values, $x2_value;
902             }
903             }
904            
905 2         39 my $x2 = matrix($r, Rstats::Func::c_logical($r, @$x2_values), $rows_count, $cols_count);
906            
907 2         15 return $x2;
908             }
909             else {
910 0         0 Carp::croak 'Error in lower_tri() : Not implemented';
911             }
912             }
913              
914             sub diag {
915 2     2 0 4 my $r = shift;
916            
917 2         14 my $x1 = to_object($r, shift);
918            
919 2         4 my $size;
920             my $x2_values;
921 2 100       15 if (Rstats::Func::get_length($r, $x1) == 1) {
922 1         21 $size = $x1->value;
923 1         3 $x2_values = [];
924 1         7 push @$x2_values, 1 for (1 .. $size);
925             }
926             else {
927 1         6 $size = Rstats::Func::get_length($r, $x1);
928 1         8 $x2_values = $x1->values;
929             }
930            
931 2         9 my $x2 = matrix($r, 0, $size, $size);
932 2         8 for (my $i = 0; $i < $size; $i++) {
933 6         40 $x2->at($i + 1, $i + 1);
934 6         34 $x2->set($x2_values->[$i]);
935             }
936              
937 2         13 return $x2;
938             }
939              
940             sub set_diag {
941 0     0 0 0 my $r = shift;
942            
943 0         0 my $x1 = to_object($r, shift);
944 0         0 my $x2 = to_object($r, shift);
945            
946 0         0 my $x2_elements;
947 0         0 my $x1_dim_values = Rstats::Func::dim($r, $x1)->values;
948 0 0       0 my $size = $x1_dim_values->[0] < $x1_dim_values->[1] ? $x1_dim_values->[0] : $x1_dim_values->[1];
949            
950 0         0 $x2 = array($r, $x2, $size);
951 0         0 my $x2_values = $x2->values;
952            
953 0         0 for (my $i = 0; $i < $size; $i++) {
954 0         0 $x1->at($i + 1, $i + 1);
955 0         0 $x1->set($x2_values->[$i]);
956             }
957            
958 0         0 return $x1;
959             }
960              
961             sub kronecker {
962 2     2 0 4 my $r = shift;
963            
964 2         8 my $x1 = to_object($r, shift);
965 2         7 my $x2 = to_object($r, shift);
966            
967 2 50       12 ($x1, $x2) = @{Rstats::Func::upgrade_type($r, [$x1, $x2])} if $x1->get_type ne $x2->get_type;
  0         0  
968            
969 2         20 my $x1_dim = Rstats::Func::dim($r, $x1);
970 2         18 my $x2_dim = Rstats::Func::dim($r, $x2);
971 2 100       25 my $dim_max_length
972             = Rstats::Func::get_length($r, $x1_dim) > Rstats::Func::get_length($r, $x2_dim) ? Rstats::Func::get_length($r, $x1_dim) : Rstats::Func::get_length($r, $x2_dim);
973            
974 2         3 my $x3_dim_values = [];
975 2         11 my $x1_dim_values = $x1_dim->values;
976 2         12 my $x2_dim_values = $x2_dim->values;
977 2         9 for (my $i = 0; $i < $dim_max_length; $i++) {
978 6   100     18 my $x1_dim_value = $x1_dim_values->[$i] || 1;
979 6   100     21 my $x2_dim_value = $x2_dim_values->[$i] || 1;
980 6         9 my $x3_dim_value = $x1_dim_value * $x2_dim_value;
981 6         19 push @$x3_dim_values, $x3_dim_value;
982             }
983            
984 2         4 my $x3_dim_product = 1;
985 2         4 $x3_dim_product *= $_ for @{$x3_dim_values};
  2         9  
986            
987 2         3 my $x3_values = [];
988 2         7 for (my $i = 0; $i < $x3_dim_product; $i++) {
989 576         2778 my $x3_index = Rstats::Util::pos_to_index($i, $x3_dim_values);
990 576         904 my $x1_index = [];
991 576         864 my $x2_index = [];
992 576         1518 for (my $k = 0; $k < @$x3_index; $k++) {
993 1728         2342 my $x3_i = $x3_index->[$k];
994            
995 1728   100     4067 my $x1_dim_value = $x1_dim_values->[$k] || 1;
996 1728   100     3895 my $x2_dim_value = $x2_dim_values->[$k] || 1;
997              
998 1728         3295 my $x1_ind = int(($x3_i - 1)/$x2_dim_value) + 1;
999 1728         2537 push @$x1_index, $x1_ind;
1000 1728         2594 my $x2_ind = $x3_i - $x2_dim_value * ($x1_ind - 1);
1001 1728         4733 push @$x2_index, $x2_ind;
1002             }
1003 576         3095 my $x1_value = $x1->value(@$x1_index);
1004 576         3277 my $x2_value = $x2->value(@$x2_index);
1005 576         16114 my $x3_value = multiply($r, $x1_value, $x2_value);
1006 576         5657 push @$x3_values, $x3_value;
1007             }
1008            
1009 2         5831 my $x3 = array($r, c_($r, @$x3_values), Rstats::Func::c_($r, @$x3_dim_values));
1010            
1011 2         1915 return $x3;
1012             }
1013              
1014             sub outer {
1015 1     1 0 2 my $r = shift;
1016            
1017 1         5 my $x1 = to_object($r, shift);
1018 1         4 my $x2 = to_object($r, shift);
1019            
1020 1 50       10 ($x1, $x2) = @{Rstats::Func::upgrade_type($r, [$x1, $x2])} if $x1->get_type ne $x2->get_type;
  0         0  
1021            
1022 1         14 my $x1_dim = Rstats::Func::dim($r, $x1);
1023 1         8 my $x2_dim = Rstats::Func::dim($r, $x2);
1024 1         2 my $x3_dim = [@{$x1_dim->values}, @{$x2_dim->values}];
  1         8  
  1         5  
1025            
1026 1         4 my $indexs = [];
1027 1         3 for my $x3_d (@$x3_dim) {
1028 4         11 push @$indexs, [1 .. $x3_d];
1029             }
1030 1         72 my $poses = Rstats::Util::cross_product($indexs);
1031            
1032 1         10 my $x1_dim_length = Rstats::Func::get_length($r, $x1_dim);
1033 1         2 my $x3_values = [];
1034 1         2 for my $pos (@$poses) {
1035 24         52 my $pos_tmp = [@$pos];
1036 24         51 my $x1_pos = [splice @$pos_tmp, 0, $x1_dim_length];
1037 24         38 my $x2_pos = $pos_tmp;
1038 24         118 my $x1_value = $x1->value(@$x1_pos);
1039 24         126 my $x2_value = $x2->value(@$x2_pos);
1040 24         46 my $x3_value = $x1_value * $x2_value;
1041 24         68 push @$x3_values, $x3_value;
1042             }
1043            
1044 1         439 my $x3 = array($r, c_($r, @$x3_values), Rstats::Func::c_($r, @$x3_dim));
1045            
1046 1         102 return $x3;
1047             }
1048              
1049              
1050              
1051             sub sub {
1052 2     2 0 4 my $r = shift;
1053            
1054 2         10 my ($x1_pattern, $x1_replacement, $x1_x, $x1_ignore_case)
1055             = args_array($r, ['pattern', 'replacement', 'x', 'ignore.case'], @_);
1056            
1057 2         13 my $pattern = $x1_pattern->value;
1058 2         11 my $replacement = $x1_replacement->value;
1059 2 100       10 my $ignore_case = defined $x1_ignore_case ? $x1_ignore_case->value : 0;
1060            
1061 2         5 my $x2_values = [];
1062 2         3 for my $x (@{$x1_x->values}) {
  2         51  
1063 6 100       14 if (!defined $x) {
1064 2         4 push @$x2_values, undef;
1065             }
1066             else {
1067 4 100       9 if ($ignore_case) {
1068 2         17 $x =~ s/$pattern/$replacement/i;
1069             }
1070             else {
1071 2         26 $x =~ s/$pattern/$replacement/;
1072             }
1073 4         12 push @$x2_values, "$x";
1074             }
1075             }
1076            
1077 2         23 my $x2 = Rstats::Func::c_character($r, @$x2_values);
1078 2         13 Rstats::Func::copy_attrs_to($r, $x1_x, $x2);
1079            
1080 2         9 return $x2;
1081             }
1082              
1083             sub gsub {
1084 2     2 0 3 my $r = shift;
1085            
1086 2         10 my ($x1_pattern, $x1_replacement, $x1_x, $x1_ignore_case)
1087             = args_array($r, ['pattern', 'replacement', 'x', 'ignore.case'], @_);
1088            
1089 2         13 my $pattern = $x1_pattern->value;
1090 2         10 my $replacement = $x1_replacement->value;
1091 2 100       10 my $ignore_case = defined $x1_ignore_case ? $x1_ignore_case->value : 0;
1092            
1093 2         4 my $x2_values = [];
1094 2         4 for my $x (@{$x1_x->values}) {
  2         10  
1095 6 100       16 if (!defined $x) {
1096 2         5 push @$x2_values, $x;
1097             }
1098             else {
1099 4 100       6 if ($ignore_case) {
1100 2         18 $x =~ s/$pattern/$replacement/gi;
1101             }
1102             else {
1103 2         20 $x =~ s/$pattern/$replacement/g;
1104             }
1105 4         11 push @$x2_values, $x;
1106             }
1107             }
1108            
1109 2         32 my $x2 = Rstats::Func::c_character($r, @$x2_values);
1110 2         14 Rstats::Func::copy_attrs_to($r, $x1_x, $x2);
1111            
1112 2         33 return $x2;
1113             }
1114              
1115             sub grep {
1116 2     2 0 4 my $r = shift;
1117            
1118 2         8 my ($x1_pattern, $x1_x, $x1_ignore_case) = args_array($r, ['pattern', 'x', 'ignore.case'], @_);
1119            
1120 2         12 my $pattern = $x1_pattern->value;
1121 2 100       12 my $ignore_case = defined $x1_ignore_case ? $x1_ignore_case->value : 0;
1122            
1123 2         5 my $x2_values = [];
1124 2         10 my $x1_x_values = $x1_x->values;
1125 2         9 for (my $i = 0; $i < @$x1_x_values; $i++) {
1126 6         11 my $x = $x1_x_values->[$i];
1127            
1128 6 100       16 unless (!defined $x) {
1129 4 100       8 if ($ignore_case) {
1130 2 50       16 if ($x =~ /$pattern/i) {
1131 2         7 push @$x2_values, $i + 1;
1132             }
1133             }
1134             else {
1135 2 100       18 if ($x =~ /$pattern/) {
1136 1         4 push @$x2_values, $i + 1;
1137             }
1138             }
1139             }
1140             }
1141            
1142 2         26 return Rstats::Func::c_double($r, @$x2_values);
1143             }
1144              
1145             sub C_ {
1146 127     127 0 239 my $r = shift;
1147 127         205 my $seq_str = shift;
1148              
1149 127         183 my $by;
1150             my $mode;
1151 127 100       445 if ($seq_str =~ s/^(.+)\*//) {
1152 1         3 $by = $1;
1153             }
1154            
1155 127         321 my $from;
1156             my $to;
1157 127 50       696 if ($seq_str =~ /([^\:]+)(?:\:(.+))?/) {
1158 127         278 $from = $1;
1159 127         252 $to = $2;
1160 127 50       316 $to = $from unless defined $to;
1161             }
1162            
1163 127         728 my $vector = seq($r,{from => $from, to => $to, by => $by});
1164            
1165 127         4959 return $vector;
1166             }
1167              
1168             sub col {
1169 1     1 0 3 my $r = shift;
1170 1         2 my $x1 = shift;
1171            
1172 1         4 my $nrow = nrow($r, $x1)->value;
1173 1         15 my $ncol = ncol($r, $x1)->value;
1174            
1175 1         14 my @values;
1176 1         5 for my $col (1 .. $ncol) {
1177 4         10 push @values, ($col) x $nrow;
1178             }
1179            
1180 1         227 return array($r, c_($r, @values), Rstats::Func::c_($r, $nrow, $ncol));
1181             }
1182              
1183             sub chartr {
1184 1     1 0 3 my $r = shift;
1185            
1186 1         5 my ($x1_old, $x1_new, $x1_x) = args_array($r, ['old', 'new', 'x'], @_);
1187            
1188 1         158 my $old = $x1_old->value;
1189 1         6 my $new = $x1_new->value;
1190            
1191 1         3 my $x2_values = [];
1192 1         2 for my $x (@{$x1_x->values}) {
  1         7  
1193 3 100       9 if (!defined $x) {
1194 1         2 push @$x2_values, $x;
1195             }
1196             else {
1197 2         4 $old =~ s#/#\/#;
1198 2         4 $new =~ s#/#\/#;
1199 2         113 eval "\$x =~ tr/$old/$new/";
1200 2 50       8 Carp::croak $@ if $@;
1201 2         6 push @$x2_values, "$x";
1202             }
1203             }
1204            
1205 1         85 my $x2 = Rstats::Func::c_character($r, @$x2_values);
1206 1         9 Rstats::Func::copy_attrs_to($r, $x1_x, $x2);
1207            
1208 1         4 return $x2;
1209             }
1210              
1211             sub charmatch {
1212 5     5 0 7 my $r = shift;
1213            
1214 5         19 my ($x1_x, $x1_table) = args_array($r, ['x', 'table'], @_);
1215            
1216 5 50 33     29 die "Error in charmatch() : Not implemented"
1217             unless $x1_x->get_type eq 'character' && $x1_table->get_type eq 'character';
1218            
1219 5         10 my $x2_values = [];
1220 5         7 for my $x1_x_value (@{$x1_x->values}) {
  5         23  
1221 6         12 my $x1_x_char = $x1_x_value;
1222 6         9 my $x1_x_char_q = quotemeta($x1_x_char);
1223 6         6 my $match_count;
1224             my $match_pos;
1225 6         28 my $x1_table_values = $x1_table->values;
1226 6         36 for (my $k = 0; $k < Rstats::Func::get_length($r, $x1_table); $k++) {
1227 16         29 my $x1_table_char = $x1_table_values->[$k];
1228 16 100       98 if ($x1_table_char =~ /$x1_x_char_q/) {
1229 10         12 $match_count++;
1230 10         51 $match_pos = $k;
1231             }
1232             }
1233 6 50       22 if ($match_count == 0) {
    100          
    50          
1234 0         0 push @$x2_values, undef;
1235             }
1236             elsif ($match_count == 1) {
1237 4         12 push @$x2_values, $match_pos + 1;
1238             }
1239             elsif ($match_count > 1) {
1240 2         7 push @$x2_values, 0;
1241             }
1242             }
1243            
1244 5         80 return Rstats::Func::c_double($r, @$x2_values);
1245             }
1246              
1247              
1248              
1249             sub nrow {
1250 5     5 0 10 my $r = shift;
1251            
1252 5         10 my $x1 = shift;
1253            
1254 5 100       52 if (Rstats::Func::is_data_frame($r, $x1)) {
    100          
1255 1         20 return Rstats::Func::c_($r, $x1->{row_length});
1256             }
1257             elsif (Rstats::Func::is_list($r, $x1)) {
1258 1         7 return Rstats::Func::NULL($r);
1259             }
1260             else {
1261 3         45 return Rstats::Func::c_($r, Rstats::Func::dim($r, $x1)->values->[0]);
1262             }
1263             }
1264              
1265             sub is_element {
1266 2     2 0 4 my $r = shift;
1267            
1268 2         11 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1269            
1270 2 50       10 Carp::croak "mode is diffrence" if $x1->get_type ne $x2->get_type;
1271            
1272 2         12 my $type = $x1->get_type;
1273 2         11 my $x1_values = $x1->values;
1274 2         13 my $x2_values = $x2->values;
1275 2         5 my $x3_values = [];
1276 2         5 for my $x1_value (@$x1_values) {
1277 8         11 my $match;
1278 8         14 for my $x2_value (@$x2_values) {
1279 18 50 66     83 if ($type eq 'character') {
    100          
    50          
1280 0 0       0 if ($x1_value eq $x2_value) {
1281 0         0 $match = 1;
1282 0         0 last;
1283             }
1284             }
1285             elsif ($type eq 'double' || $type eq 'integer') {
1286 9 100       21 if ($x1_value == $x2_value) {
1287 3         4 $match = 1;
1288 3         4 last;
1289             }
1290             }
1291             elsif ($type eq 'complex') {
1292 9 100 66     52 if ($x1_value->{re} == $x2_value->{re} && $x1_value->{im} == $x2_value->{im}) {
1293 3         5 $match = 1;
1294 3         4 last;
1295             }
1296             }
1297             }
1298 8 100       21 push @$x3_values, $match ? 1 : 0;
1299             }
1300            
1301 2         31 return Rstats::Func::c_logical($r, @$x3_values);
1302             }
1303              
1304             sub setequal {
1305 3     3 0 5 my $r = shift;
1306            
1307 3         16 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1308            
1309 3 50       16 Carp::croak "mode is diffrence" if $x1->get_type ne $x2->get_type;
1310            
1311 3         10 my $x3 = Rstats::Func::sort($r, $x1);
1312 3         28 my $x4 = Rstats::Func::sort($r, $x2);
1313            
1314 3 100       61 return Rstats::Func::FALSE($r) if Rstats::Func::get_length($r, $x3) ne Rstats::Func::get_length($r, $x4);
1315            
1316 2         3 my $not_equal;
1317 2         30 my $x3_elements = Rstats::Func::decompose($r, $x3);
1318 2         30 my $x4_elements = Rstats::Func::decompose($r, $x4);
1319 2         19 for (my $i = 0; $i < Rstats::Func::get_length($r, $x3); $i++) {
1320 4 100       14 unless ($x3_elements->[$i] == $x4_elements->[$i]) {
1321 1         2 $not_equal = 1;
1322 1         3 last;
1323             }
1324             }
1325            
1326 2 100       54 return $not_equal ? Rstats::Func::FALSE($r) : TRUE($r);
1327             }
1328              
1329             sub setdiff {
1330 1     1 0 3 my $r = shift;
1331            
1332 1         6 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1333            
1334 1 50       6 Carp::croak "mode is diffrence" if $x1->get_type ne $x2->get_type;
1335            
1336 1         22 my $x1_elements = Rstats::Func::decompose($r, $x1);
1337 1         13 my $x2_elements = Rstats::Func::decompose($r, $x2);
1338 1         4 my $x3_elements = [];
1339 1         2 for my $x1_element (@$x1_elements) {
1340 4         6 my $match;
1341 4         6 for my $x2_element (@$x2_elements) {
1342 7 100       20 if ($x1_element == $x2_element) {
1343 2         5 $match = 1;
1344 2         3 last;
1345             }
1346             }
1347 4 100       23 push @$x3_elements, $x1_element unless $match;
1348             }
1349              
1350 1         38 return Rstats::Func::c_($r, @$x3_elements);
1351             }
1352              
1353             sub intersect {
1354 1     1 0 4 my $r = shift;
1355            
1356 1         6 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1357            
1358 1 50       8 Carp::croak "mode is diffrence" if $x1->get_type ne $x2->get_type;
1359            
1360 1         20 my $x1_elements = Rstats::Func::decompose($r, $x1);
1361 1         18 my $x2_elements = Rstats::Func::decompose($r, $x2);
1362 1         3 my $x3_elements = [];
1363 1         3 for my $x1_element (@$x1_elements) {
1364 4         6 for my $x2_element (@$x2_elements) {
1365 16 100       45 if ($x1_element == $x2_element) {
1366 2         11 push @$x3_elements, $x1_element;
1367             }
1368             }
1369             }
1370            
1371 1         32 return Rstats::Func::c_($r, @$x3_elements);
1372             }
1373              
1374             sub union {
1375 1     1 0 3 my $r = shift;
1376            
1377 1         7 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1378              
1379 1 50       7 Carp::croak "mode is diffrence" if $x1->get_type ne $x2->get_type;
1380            
1381 1         19 my $x3 = Rstats::Func::c_($r, $x1, $x2);
1382 1         6 my $x4 = unique($r, $x3);
1383            
1384 1         19 return $x4;
1385             }
1386              
1387             sub diff {
1388 2     2 0 4 my $r = shift;
1389            
1390 2         7 my $x1 = to_object($r, shift);
1391            
1392 2         4 my $x2_elements = [];
1393 2         36 my $x1_elements = Rstats::Func::decompose($r, $x1);
1394 2         15 for (my $i = 0; $i < Rstats::Func::get_length($r, $x1) - 1; $i++) {
1395 5         9 my $x1_element1 = $x1_elements->[$i];
1396 5         8 my $x1_element2 = $x1_elements->[$i + 1];
1397 5         15 my $x2_element = $x1_element2 - $x1_element1;
1398 5         37 push @$x2_elements, $x2_element;
1399             }
1400 2         39 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1401 2         14 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1402            
1403 2         29 return $x2;
1404             }
1405              
1406             sub nchar {
1407 1     1 0 2 my $r = shift;
1408 1         4 my $x1 = to_object($r, shift);
1409            
1410 1 50       7 if ($x1->get_type eq 'character') {
1411 1         3 my $x2_elements = [];
1412 1         2 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  1         18  
1413 3 100       39 if (Rstats::Func::is_na($r, $x1_element)) {
1414 1         6 push @$x2_elements, $x1_element;
1415             }
1416             else {
1417 2         6 my $x2_element = Rstats::Func::c_integer($r, CORE::length Rstats::Func::value($r, $x1_element));
1418 2         11 push @$x2_elements, $x2_element;
1419             }
1420             }
1421 1         80 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1422 1         21 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1423            
1424 1         10 return $x2;
1425             }
1426             else {
1427 0         0 Carp::croak "Error in nchar() : Not implemented";
1428             }
1429             }
1430              
1431             sub tolower {
1432 1     1 0 3 my $r = shift;
1433            
1434 1         4 my $x1 = to_object($r, shift);
1435            
1436 1 50       7 if ($x1->get_type eq 'character') {
1437 1         3 my $x2_elements = [];
1438 1         2 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  1         24  
1439 3 100       38 if (Rstats::Func::is_na($r, $x1_element)) {
1440 1         6 push @$x2_elements, $x1_element;
1441             }
1442             else {
1443 2         7 my $x2_element = Rstats::Func::c_character($r, lc Rstats::Func::value($r, $x1_element));
1444 2         13 push @$x2_elements, $x2_element;
1445             }
1446             }
1447 1         26 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1448 1         8 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1449            
1450 1         11 return $x2;
1451             }
1452             else {
1453 0         0 return $x1;
1454             }
1455             }
1456              
1457             sub toupper {
1458 1     1 0 3 my $r = shift;
1459            
1460 1         4 my $x1 = to_object($r, shift);
1461            
1462 1 50       7 if ($x1->get_type eq 'character') {
1463 1         3 my $x2_elements = [];
1464 1         2 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  1         18  
1465 3 100       44 if (Rstats::Func::is_na($r, $x1_element)) {
1466 1         6 push @$x2_elements, $x1_element;
1467             }
1468             else {
1469 2         7 my $x2_element = Rstats::Func::c_character($r, uc Rstats::Func::value($r, $x1_element));
1470 2         12 push @$x2_elements, $x2_element;
1471             }
1472             }
1473 1         27 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1474 1         8 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1475            
1476 1         10 return $x2;
1477             }
1478             else {
1479 0         0 return $x1;
1480             }
1481             }
1482              
1483             sub match {
1484 1     1 0 3 my $r = shift;
1485            
1486 1         8 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1487            
1488 1         19 my $x1_elements = Rstats::Func::decompose($r, $x1);
1489 1         21 my $x2_elements = Rstats::Func::decompose($r, $x2);
1490 1         3 my @matches;
1491 1         3 for my $x1_element (@$x1_elements) {
1492 4         5 my $i = 1;
1493 4         7 my $match;
1494 4         6 for my $x2_element (@$x2_elements) {
1495 15 100       39 if ($x1_element == $x2_element) {
1496 2         4 $match = 1;
1497 2         4 last;
1498             }
1499 13         62 $i++;
1500             }
1501 4 100       16 if ($match) {
1502 2         5 push @matches, $i;
1503             }
1504             else {
1505 2         5 push @matches, undef;
1506             }
1507             }
1508            
1509 1         122 return Rstats::Func::c_double($r, @matches);
1510             }
1511              
1512              
1513              
1514             sub append {
1515 3     3 0 6 my $r = shift;
1516            
1517 3         11 my ($x1, $x2, $x_after) = args_array($r, ['x1', 'x2', 'after'], @_);
1518            
1519             # Default
1520 3 100       18 $x_after = NULL($r) unless defined $x_after;
1521            
1522 3         39 my $x1_length = Rstats::Func::get_length($r, $x1);
1523 3 100       28 $x_after = Rstats::Func::c_($r, $x1_length) if Rstats::Func::is_null($r, $x_after);
1524 3         31 my $after = $x_after->value;
1525            
1526 3         60 my $x1_elements = Rstats::Func::decompose($r, $x1);
1527 3         29 my $x2_elements = Rstats::Func::decompose($r, $x2);
1528 3         8 my @x3_elements = @$x1_elements;
1529 3         8 splice @x3_elements, $after, 0, @$x2_elements;
1530            
1531 3         93 my $x3 = Rstats::Func::c_($r, @x3_elements);
1532            
1533 3         55 return $x3;
1534             }
1535              
1536              
1537              
1538             sub cbind {
1539 4     4 0 10 my $r = shift;
1540            
1541 4         11 my @xs = @_;
1542              
1543 4 50       18 return Rstats::Func::NULL($r) unless @xs;
1544            
1545 4 100       96 if (Rstats::Func::is_data_frame($r, $xs[0])) {
1546             # Check row count
1547 2         4 my $first_row_length;
1548             my $different;
1549 2         5 for my $x (@xs) {
1550 4 100       11 if ($first_row_length) {
1551 2 50       9 $different = 1 if $x->{row_length} != $first_row_length;
1552             }
1553             else {
1554 2         6 $first_row_length = $x->{row_length};
1555             }
1556             }
1557 2 50       7 Carp::croak "cbind need same row count data frame"
1558             if $different;
1559            
1560             # Create new data frame
1561 2         4 my @data_frame_args;
1562 2         4 for my $x (@xs) {
1563 4         50 my $names = Rstats::Func::names($r, $x)->values;
1564 4         23 for my $name (@$names) {
1565 6         30 push @data_frame_args, $name, $x->getin($name);
1566             }
1567             }
1568 2         19 my $data_frame = Rstats::Func::data_frame($r, @data_frame_args);
1569            
1570 2         13 return $data_frame;
1571             }
1572             else {
1573 2         4 my $row_count_needed;
1574             my $col_count_total;
1575 2         3 my $x2_elements = [];
1576 2         6 for my $_x (@xs) {
1577            
1578 6         25 my $x1 = to_object($r, $_x);
1579 6         45 my $x1_dim_elements = Rstats::Func::decompose($r, Rstats::Func::dim($r, $x1));
1580            
1581 6         15 my $row_count;
1582 6 50       71 if (Rstats::Func::is_matrix($r, $x1)) {
    50          
1583 0         0 $row_count = $x1_dim_elements->[0];
1584 0         0 $col_count_total += $x1_dim_elements->[1];
1585             }
1586             elsif (Rstats::Func::is_vector($r, $x1)) {
1587 6         31 $row_count = $x1->dim_as_array->values->[0];
1588 6         33 $col_count_total += 1;
1589             }
1590             else {
1591 0         0 Carp::croak "cbind or rbind can only receive matrix and vector";
1592             }
1593            
1594 6 100       44 $row_count_needed = $row_count unless defined $row_count_needed;
1595 6 50       40 Carp::croak "Row count is different" if $row_count_needed ne $row_count;
1596            
1597 6         8 push @$x2_elements, @{Rstats::Func::decompose($r, $x1)};
  6         119  
1598             }
1599 2         103 my $matrix = matrix($r, c_($r, @$x2_elements), $row_count_needed, $col_count_total);
1600            
1601 2         48 return $matrix;
1602             }
1603             }
1604              
1605             sub ceiling {
1606 2     2 0 3 my $r = shift;
1607 2         5 my $_x1 = shift;
1608            
1609 2         6 my $x1 = to_object($r, $_x1);
1610             my @x2_elements
1611 8         19 = map { Rstats::Func::c_double($r, POSIX::ceil Rstats::Func::value($r, $_)) }
1612 2         4 @{Rstats::Func::decompose($r, $x1)};
  2         38  
1613            
1614 2         63 my $x2 = Rstats::Func::c_($r, @x2_elements);
1615 2         20 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1616            
1617 2         46 Rstats::Func::mode($r, $x2, 'double');
1618            
1619 2         32 return $x2;
1620             }
1621              
1622             sub colMeans {
1623 1     1 0 5 my $r = shift;
1624 1         3 my $x1 = shift;
1625            
1626 1         18 my $dim_values = Rstats::Func::dim($r, $x1)->values;
1627 1 50       9 if (@$dim_values == 2) {
1628 1         3 my $x1_values = [];
1629 1         4 for my $row (1 .. $dim_values->[0]) {
1630 4         7 my $x1_value = 0;
1631 4         26 $x1_value += $x1->value($row, $_) for (1 .. $dim_values->[1]);
1632 4         11 push @$x1_values, $x1_value / $dim_values->[1];
1633             }
1634 1         53 return Rstats::Func::c_($r, @$x1_values);
1635             }
1636             else {
1637 0         0 Carp::croak "Can't culculate colSums";
1638             }
1639             }
1640              
1641             sub colSums {
1642 1     1 0 4 my $r = shift;
1643 1         2 my $x1 = shift;
1644            
1645 1         19 my $dim_values = Rstats::Func::dim($r, $x1)->values;
1646 1 50       9 if (@$dim_values == 2) {
1647 1         2 my $x1_values = [];
1648 1         4 for my $row (1 .. $dim_values->[0]) {
1649 4         5 my $x1_value = 0;
1650 4         26 $x1_value += $x1->value($row, $_) for (1 .. $dim_values->[1]);
1651 4         11 push @$x1_values, $x1_value;
1652             }
1653 1         39 return Rstats::Func::c_($r, @$x1_values);
1654             }
1655             else {
1656 0         0 Carp::croak "Can't culculate colSums";
1657             }
1658             }
1659              
1660              
1661              
1662              
1663              
1664             sub cummax {
1665 1     1 0 3 my $r = shift;
1666            
1667 1         5 my $x1 = to_object($r, shift);
1668            
1669 1 50       7 unless (Rstats::Func::get_length($r, $x1)) {
1670 0         0 Carp::carp 'no non-missing arguments to max; returning -Inf';
1671 0         0 return -(Rstats::Func::Inf($r));
1672             }
1673            
1674 1         3 my @x2_elements;
1675 1         18 my $x1_elements = Rstats::Func::decompose($r, $x1);
1676 1         3 my $max = shift @$x1_elements;
1677 1         2 push @x2_elements, $max;
1678 1         3 for my $element (@$x1_elements) {
1679            
1680 3 50       39 if (Rstats::Func::is_na($r, $element)) {
    50          
1681 0         0 return Rstats::Func::NA($r);
1682             }
1683             elsif (Rstats::Func::is_nan($r, $element)) {
1684 0         0 $max = $element;
1685             }
1686 3 100 66     24 if ($element > $max && !Rstats::Func::is_nan($r, $max)) {
1687 2         4 $max = $element;
1688             }
1689 3         19 push @x2_elements, $max;
1690             }
1691            
1692 1         31 return Rstats::Func::c_($r, @x2_elements);
1693             }
1694              
1695             sub cummin {
1696 1     1 0 2 my $r = shift;
1697            
1698 1         5 my $x1 = to_object($r, shift);
1699            
1700 1 50       7 unless (Rstats::Func::get_length($r, $x1)) {
1701 0         0 Carp::carp 'no non-missing arguments to max; returning -Inf';
1702 0         0 return -(Rstats::Func::Inf($r));
1703             }
1704            
1705 1         2 my @x2_elements;
1706 1         19 my $x1_elements = Rstats::Func::decompose($r, $x1);
1707 1         3 my $min = shift @$x1_elements;
1708 1         2 push @x2_elements, $min;
1709 1         3 for my $element (@$x1_elements) {
1710 3 50       40 if (Rstats::Func::is_na($r, $element)) {
    50          
1711 0         0 return Rstats::Func::NA($r);
1712             }
1713             elsif (Rstats::Func::is_nan($r, $element)) {
1714 0         0 $min = $element;
1715             }
1716 3 100 66     24 if ($element < $min && !Rstats::Func::is_nan($r, $min)) {
1717 2         4 $min = $element;
1718             }
1719 3         20 push @x2_elements, $min;
1720             }
1721            
1722 1         30 return Rstats::Func::c_($r, @x2_elements);
1723             }
1724              
1725              
1726              
1727             sub args_array {
1728 368     368 0 560 my $r = shift;
1729            
1730 368         482 my $names = shift;
1731 368 100       1112 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
1732 368         493 my @args;
1733 368         1048 for (my $i = 0; $i < @$names; $i++) {
1734 1460         2074 my $name = $names->[$i];
1735 1460         1533 my $arg;
1736 1460 100       3962 if (exists $opt->{$name}) {
    100          
1737 140         553 $arg = to_object($r, delete $opt->{$name});
1738             }
1739             elsif ($i < @_) {
1740 592         3074 $arg = to_object($r, $_[$i]);
1741             }
1742 1460         4032 push @args, $arg;
1743             }
1744            
1745 368         1081 Carp::croak "unused argument ($_)" for keys %$opt;
1746            
1747 368         1205 return @args;
1748             }
1749              
1750             sub complex {
1751 39     39 0 63 my $r = shift;
1752              
1753 39         148 my ($x1_re, $x1_im, $x1_mod, $x1_arg) = args_array($r, ['re', 'im', 'mod', 'arg'], @_);
1754            
1755 39 100       283 $x1_mod = Rstats::Func::NULL($r) unless defined $x1_mod;
1756 39 100       201 $x1_arg = Rstats::Func::NULL($r) unless defined $x1_arg;
1757              
1758 39         67 my $x2_elements = [];
1759             # Create complex from mod and arg
1760 39 100 100     390 if (Rstats::Func::get_length($r, $x1_mod) || Rstats::Func::get_length($r, $x1_arg)) {
1761 3         12 my $x1_mod_length = Rstats::Func::get_length($r, $x1_mod);
1762 3         11 my $x1_arg_length = Rstats::Func::get_length($r, $x1_arg);
1763 3 100       9 my $longer_length = $x1_mod_length > $x1_arg_length ? $x1_mod_length : $x1_arg_length;
1764            
1765 3         24 my $x1_mod_elements = Rstats::Func::decompose($r, $x1_mod);
1766 3         21 my $x1_arg_elements = Rstats::Func::decompose($r, $x1_arg);
1767 3         11 for (my $i = 0; $i < $longer_length; $i++) {
1768 3         5 my $x_mod = $x1_mod_elements->[$i];
1769 3 100       17 $x_mod = Rstats::Func::c_double($r, 1) unless defined $x_mod;
1770 3         5 my $x_arg = $x1_arg_elements->[$i];
1771 3 100       17 $x_arg = Rstats::Func::c_double($r, 0) unless defined $x_arg;
1772            
1773 3         67 my $x_re = $x_mod * Rstats::Func::cos($r, $x_arg);
1774 3         64 my $x_im = $x_mod * Rstats::Func::sin($r, $x_arg);
1775            
1776 3         24 my $x2_element = Rstats::Func::complex($r, $x_re, $x_im);
1777 3         38 push @$x2_elements, $x2_element;
1778             }
1779             }
1780             # Create complex from re and im
1781             else {
1782 36 50 33     391 Carp::croak "mode should be numeric"
1783             unless Rstats::Func::is_numeric($r, $x1_re) && Rstats::Func::is_numeric($r, $x1_im);
1784            
1785 36         496 my $x1_re_elements = Rstats::Func::decompose($r, $x1_re);
1786 36         310 my $x1_im_elements = Rstats::Func::decompose($r, $x1_im);
1787 36         214 for (my $i = 0; $i < Rstats::Func::get_length($r, $x1_im); $i++) {
1788 40         48 my $x_re;
1789 40 100       96 if (defined $x1_re_elements->[$i]) {
1790 39         59 $x_re = $x1_re_elements->[$i];
1791             }
1792             else {
1793 1         10 $x_re = Rstats::Func::c_double($r, 0);
1794             }
1795 40         57 my $x_im = $x1_im_elements->[$i];
1796 40         90 my $x2_element = Rstats::Func::c_complex(
1797             $r,
1798             {re => Rstats::Func::value($r, $x_re), im => Rstats::Func::value($r, $x_im)}
1799             );
1800 40         523 push @$x2_elements, $x2_element;
1801             }
1802             }
1803            
1804 39         843 return Rstats::Func::c_($r, @$x2_elements);
1805             }
1806              
1807              
1808             sub floor {
1809 2     2 0 4 my $r = shift;
1810            
1811 2         3 my $_x1 = shift;
1812            
1813 2         8 my $x1 = to_object($r, $_x1);
1814            
1815             my @x2_elements
1816 8         19 = map { Rstats::Func::c_double($r, POSIX::floor Rstats::Func::value($r, $_)) }
1817 2         3 @{Rstats::Func::decompose($r, $x1)};
  2         39  
1818              
1819 2         64 my $x2 = Rstats::Func::c_($r, @x2_elements);
1820 2         19 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1821 2         45 Rstats::Func::mode($r, $x2, 'double');
1822            
1823 2         31 return $x2;
1824             }
1825              
1826             sub head {
1827 5     5 0 10 my $r = shift;
1828            
1829 5         23 my ($x1, $x_n) = args_array($r, ['x1', 'n'], @_);
1830            
1831 5 100       27 my $n = defined $x_n ? $x_n->value : 6;
1832            
1833 5 100       51 if (Rstats::Func::is_data_frame($r, $x1)) {
1834 2 50       9 my $max = $x1->{row_length} < $n ? $x1->{row_length} : $n;
1835            
1836 2         10 my $x_range = Rstats::Func::C_($r, "1:$max");
1837 2         19 my $x2 = $x1->get($x_range, Rstats::Func::NULL($r));
1838            
1839 2         13 return $x2;
1840             }
1841             else {
1842 3         58 my $x1_elements = Rstats::Func::decompose($r, $x1);
1843 3 100       22 my $max = Rstats::Func::get_length($r, $x1) < $n ? Rstats::Func::get_length($r, $x1) : $n;
1844 3         4 my @x2_elements;
1845 3         8 for (my $i = 0; $i < $max; $i++) {
1846 12         29 push @x2_elements, $x1_elements->[$i];
1847             }
1848            
1849 3         70 my $x2 = Rstats::Func::c_($r, @x2_elements);
1850 3         22 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1851            
1852 3         40 return $x2;
1853             }
1854             }
1855              
1856             sub i_ {
1857 119     119 0 191 my $r = shift;
1858            
1859 119         1431 my $i = Rstats::Func::c_complex($r, {re => 0, im => 1});
1860            
1861 119         2102 return Rstats::Func::c_($r, $i);
1862             }
1863              
1864             sub ifelse {
1865 1     1 0 2 my $r = shift;
1866            
1867 1         3 my ($_x1, $value1, $value2) = @_;
1868            
1869 1         5 my $x1 = to_object($r, $_x1);
1870 1         7 my $x1_values = $x1->values;
1871 1         3 my @x2_values;
1872 1         3 for my $x1_value (@$x1_values) {
1873 3         5 local $_ = $x1_value;
1874 3 100       7 if ($x1_value) {
1875 2         5 push @x2_values, $value1;
1876             }
1877             else {
1878 1         3 push @x2_values, $value2;
1879             }
1880             }
1881            
1882 1         89 return Rstats::Func::array($r, c_($r, @x2_values));
1883             }
1884              
1885              
1886              
1887             sub max {
1888 6     6 0 10 my $r = shift;
1889              
1890 6         10 my @args = grep { !Rstats::Func::is_null($r, $_) } @_;
  7         68  
1891            
1892 6         85 my $x1 = Rstats::Func::c_($r, @args);
1893            
1894 6 100       38 unless (Rstats::Func::get_length($r, $x1)) {
1895 1         172 Carp::carp 'no non-missing arguments to max; returning -Inf';
1896 1         126 return -(Rstats::Func::Inf($r));
1897             }
1898            
1899 5         80 my $x1_elements = Rstats::Func::decompose($r, $x1);
1900 5         11 my $max = shift @$x1_elements;
1901 5         11 for my $element (@$x1_elements) {
1902            
1903 14 100       167 if (Rstats::Func::is_na($r, $element)) {
    100          
1904 1         18 return Rstats::Func::NA($r);
1905             }
1906             elsif (Rstats::Func::is_nan($r, $element)) {
1907 2         5 $max = $element;
1908             }
1909 13 100 66     217 if (!Rstats::Func::is_nan($r, $max) && Rstats::Func::value($r, $element > $max)) {
1910 11         79 $max = $element;
1911             }
1912             }
1913            
1914 4         87 return Rstats::Func::c_($r, $max);
1915             }
1916              
1917             sub mean {
1918 4     4 0 7 my $r = shift;
1919            
1920 4         13 my $x1 = to_object($r, shift);
1921            
1922 4         136 my $x2 = divide($r, sum($r, $x1), Rstats::Func::get_length($r, $x1));
1923            
1924 4         34 return $x2;
1925             }
1926              
1927             sub min {
1928 6     6 0 11 my $r = shift;
1929            
1930 6         11 my @args = grep { !Rstats::Func::is_null($r, $_) } @_;
  7         67  
1931            
1932 6         81 my $x1 = Rstats::Func::c_($r, @args);
1933            
1934 6 100       39 unless (Rstats::Func::get_length($r, $x1)) {
1935 1         179 Carp::carp 'no non-missing arguments to min; returning Inf';
1936 1         97 return Rstats::Func::Inf($r);
1937             }
1938            
1939 5         91 my $x1_elements = Rstats::Func::decompose($r, $x1);
1940 5         11 my $min = shift @$x1_elements;
1941 5         11 for my $element (@$x1_elements) {
1942            
1943 14 100       172 if (Rstats::Func::is_na($r, $element)) {
    100          
1944 1         16 return Rstats::Func::NA($r);
1945             }
1946             elsif (Rstats::Func::is_nan($r, $element)) {
1947 2         4 $min = $element;
1948             }
1949 13 50 66     220 if (!Rstats::Func::is_nan($r, $min) && Rstats::Func::value($r, $element < $min)) {
1950 0         0 $min = $element;
1951             }
1952             }
1953            
1954 4         89 return Rstats::Func::c_($r, $min);
1955             }
1956              
1957             sub order {
1958 5     5 0 8 my $r = shift;
1959 5 100       17 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
1960 5         8 my @xs = map { to_object($r, $_) } @_;
  7         27  
1961            
1962 5         10 my @xs_values;
1963 5         8 for my $x (@xs) {
1964 7         36 push @xs_values, $x->values;
1965             }
1966              
1967 5   66     32 my $decreasing = $opt->{decreasing} || Rstats::Func::FALSE($r);
1968            
1969 5         9 my @pos_vals;
1970 5         8 for my $i (0 .. @{$xs_values[0]} - 1) {
  5         15  
1971 24         50 my $pos_val = {pos => $i + 1};
1972 24         42 $pos_val->{val} = [];
1973 24         51 push @{$pos_val->{val}}, $xs_values[$_][$i] for (0 .. @xs_values);
  108         215  
1974 24         45 push @pos_vals, $pos_val;
1975             }
1976            
1977             my @sorted_pos_values = !$decreasing
1978             ? sort {
1979 21         24 my $comp;
1980 21         50 for (my $i = 0; $i < @xs_values; $i++) {
1981 24         42 $comp = $a->{val}[$i] <=> $b->{val}[$i];
1982 24 100       57 last if $comp != 0;
1983             }
1984             $comp;
1985             } @pos_vals
1986             : sort {
1987 5 100       18 my $comp;
  16         19  
1988 16         37 for (my $i = 0; $i < @xs_values; $i++) {
1989 19         33 $comp = $b->{val}[$i] <=> $a->{val}[$i];
1990 19 100       42 last if $comp != 0;
1991             }
1992             $comp;
1993             } @pos_vals;
1994 5         9 my @orders = map { $_->{pos} } @sorted_pos_values;
  24         40  
1995            
1996 5         269 return Rstats::Func::c_($r, @orders);
1997             }
1998              
1999             # TODO
2000             # na.last
2001             sub rank {
2002 1     1 0 3 my $r = shift;
2003            
2004 1 50       6 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2005 1         4 my $x1 = to_object($r, shift);
2006 1         4 my $decreasing = $opt->{decreasing};
2007            
2008 1         7 my $x1_values = $x1->values;
2009            
2010 1         3 my @pos_vals;
2011 1         16 push @pos_vals, {pos => $_ + 1, value => $x1_values->[$_]} for (0 .. @$x1_values - 1);
2012 1         6 my @sorted_pos_values = sort { $a->{value} <=> $b->{value} } @pos_vals;
  13         22  
2013            
2014             # Rank
2015 1         5 for (my $i = 0; $i < @sorted_pos_values; $i++) {
2016 7         19 $sorted_pos_values[$i]{rank} = $i + 1;
2017             }
2018            
2019             # Average rank
2020 1         3 my $element_info = {};
2021 1         2 for my $sorted_pos_value (@sorted_pos_values) {
2022 7         11 my $value = $sorted_pos_value->{value};
2023 7   100     24 $element_info->{$value} ||= {};
2024 7         12 $element_info->{$value}{rank_total} += $sorted_pos_value->{rank};
2025 7         13 $element_info->{$value}{rank_count}++;
2026             }
2027            
2028 1         2 for my $sorted_pos_value (@sorted_pos_values) {
2029 7         10 my $value = $sorted_pos_value->{value};
2030             $sorted_pos_value->{rank_average}
2031 7         16 = $element_info->{$value}{rank_total} / $element_info->{$value}{rank_count};
2032             }
2033            
2034 1         4 my @sorted_pos_values2 = sort { $a->{pos} <=> $b->{pos} } @sorted_pos_values;
  14         21  
2035 1         2 my @rank = map { $_->{rank_average} } @sorted_pos_values2;
  7         12  
2036            
2037 1         91 return Rstats::Func::c_($r, @rank);
2038             }
2039              
2040             sub paste {
2041 3     3 0 7 my $r = shift;
2042            
2043 3 100       12 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2044 3         8 my $sep = $opt->{sep};
2045 3 100       10 $sep = ' ' unless defined $sep;
2046            
2047 3         5 my $str = shift;
2048 3         4 my $x1 = shift;
2049            
2050 3         18 my $x1_values = $x1->values;
2051 3         8 my $x2_values = [];
2052 3         41 push @$x2_values, "$str$sep$_" for @$x1_values;
2053            
2054 3         101 return Rstats::Func::c_($r, @$x2_values);
2055             }
2056              
2057             sub pmax {
2058 1     1 0 2 my $r = shift;
2059            
2060 1         3 my @vs = @_;
2061            
2062 1         2 my @maxs;
2063 1         3 for my $v (@vs) {
2064 2         45 my $elements = Rstats::Func::decompose($r, $v);
2065 2         7 for (my $i = 0; $i <@$elements; $i++) {
2066 8 100 100     37 $maxs[$i] = $elements->[$i]
2067             if !defined $maxs[$i] || $elements->[$i] > $maxs[$i]
2068             }
2069             }
2070            
2071 1         27 return Rstats::Func::c_($r, @maxs);
2072             }
2073              
2074             sub pmin {
2075 1     1 0 2 my $r = shift;
2076            
2077 1         3 my @vs = @_;
2078            
2079 1         2 my @mins;
2080 1         2 for my $v (@vs) {
2081 2         37 my $elements = Rstats::Func::decompose($r, $v);
2082 2         9 for (my $i = 0; $i <@$elements; $i++) {
2083 8 100 100     42 $mins[$i] = $elements->[$i]
2084             if !defined $mins[$i] || $elements->[$i] < $mins[$i];
2085             }
2086             }
2087            
2088 1         28 return Rstats::Func::c_($r, @mins);
2089             }
2090              
2091              
2092              
2093             sub range {
2094 1     1 0 3 my $r = shift;
2095            
2096 1         2 my $x1 = shift;
2097            
2098 1         4 my $min = min($r, $x1);
2099 1         8 my $max = max($r, $x1);
2100            
2101 1         23 return Rstats::Func::c_($r, $min, $max);
2102             }
2103              
2104             sub rbind {
2105 2     2 0 8 my $r = shift;
2106 2         5 my (@xs) = @_;
2107            
2108 2 50       9 return Rstats::Func::NULL($r) unless @xs;
2109            
2110 2 100       25 if (Rstats::Func::is_data_frame($r, $xs[0])) {
2111            
2112             # Check names
2113 1         2 my $first_names;
2114 1         3 for my $x (@xs) {
2115 2 100       6 if ($first_names) {
2116 1         14 my $names = Rstats::Func::names($r, $x)->values;
2117 1         5 my $different;
2118 1 50       18 $different = 1 if @$first_names != @$names;
2119 1         5 for (my $i = 0; $i < @$first_names; $i++) {
2120 2 50       11 $different = 1 if $names->[$i] ne $first_names->[$i];
2121             }
2122 1 50       5 Carp::croak "rbind require same names having data frame"
2123             if $different;
2124             }
2125             else {
2126 1         21 $first_names = Rstats::Func::names($r, $x)->values;
2127             }
2128             }
2129            
2130             # Create new vectors
2131 1         2 my @new_vectors;
2132 1         3 for my $name (@$first_names) {
2133 2         3 my @vectors;
2134 2         6 for my $x (@xs) {
2135 4         22 my $v = $x->getin($name);
2136 4 100       82 if (Rstats::Func::is_factor($r, $v)) {
2137 2         148 push @vectors, Rstats::Func::as_character($r, $v);
2138             }
2139             else {
2140 2         19 push @vectors, $v;
2141             }
2142             }
2143 2         39 my $new_vector = Rstats::Func::c_($r, @vectors);
2144 2         13 push @new_vectors, $new_vector;
2145             }
2146            
2147             # Create new data frame
2148 1         2 my @data_frame_args;
2149 1         5 for (my $i = 0; $i < @$first_names; $i++) {
2150 2         8 push @data_frame_args, $first_names->[$i], $new_vectors[$i];
2151             }
2152 1         4 my $data_frame = Rstats::Func::data_frame($r, @data_frame_args);
2153            
2154 1         15 return $data_frame;
2155             }
2156             else {
2157 1         7 my $matrix = cbind($r, @xs);
2158            
2159 1         7 return Rstats::Func::t($r, $matrix);
2160             }
2161             }
2162              
2163             sub rep {
2164 11     11 0 16 my $r = shift;
2165            
2166 11         51 my ($x1, $x_times) = args_array($r, ['x1', 'times'], @_);
2167            
2168 11 50       72 my $times = defined $x_times ? $x_times->value : 1;
2169            
2170 11         22 my $elements = [];
2171 11         36 push @$elements, @{Rstats::Func::decompose($r, $x1)} for 1 .. $times;
  33         360  
2172 11         239 my $x2 = Rstats::Func::c_($r, @$elements);
2173            
2174 11         138 return $x2;
2175             }
2176              
2177             sub replace {
2178 3     3 0 6 my $r = shift;
2179            
2180 3         11 my $x1 = to_object($r, shift);
2181 3         8 my $x2 = to_object($r, shift);
2182 3         12 my $x3 = to_object($r, shift);
2183            
2184 3         107 my $x1_elements = Rstats::Func::decompose($r, $x1);
2185 3         44 my $x2_elements = Rstats::Func::decompose($r, $x2);
2186 3         6 my $x2_elements_h = {};
2187 3         8 for my $x2_element (@$x2_elements) {
2188 9         21 my $x2_element_hash = Rstats::Func::to_string($r, $x2_element);
2189            
2190 9         24 $x2_elements_h->{$x2_element_hash}++;
2191             Carp::croak "replace second argument can't have duplicate number"
2192 9 50       28 if $x2_elements_h->{$x2_element_hash} > 1;
2193             }
2194 3         37 my $x3_elements = Rstats::Func::decompose($r, $x3);
2195 3         5 my $x3_length = @{$x3_elements};
  3         7  
2196            
2197 3         5 my $x4_elements = [];
2198 3         10 my $replace_count = 0;
2199 3         10 for (my $i = 0; $i < @$x1_elements; $i++) {
2200 30         331 my $hash = Rstats::Func::to_string($r, Rstats::Func::c_double($r, $i + 1));
2201 30 100       162 if ($x2_elements_h->{$hash}) {
2202 9         22 push @$x4_elements, $x3_elements->[$replace_count % $x3_length];
2203 9         26 $replace_count++;
2204             }
2205             else {
2206 21         78 push @$x4_elements, $x1_elements->[$i];
2207             }
2208             }
2209            
2210 3         546 return Rstats::Func::array($r, c_($r, @$x4_elements));
2211             }
2212              
2213             sub rev {
2214 1     1 0 3 my $r = shift;
2215            
2216 1         2 my $x1 = shift;
2217            
2218             # Reverse elements
2219 1         1 my @x2_elements = reverse @{Rstats::Func::decompose($r, $x1)};
  1         21  
2220 1         26 my $x2 = Rstats::Func::c_($r, @x2_elements);
2221 1         9 Rstats::Func::copy_attrs_to($r, $x1, $x2);
2222            
2223 1         12 return $x2;
2224             }
2225              
2226             sub rnorm {
2227 1     1 0 3 my $r = shift;
2228            
2229             # Option
2230 1 50       4 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2231            
2232             # Count
2233 1         2 my ($count, $mean, $sd) = @_;
2234 1 50       10 Carp::croak "rnorm count should be bigger than 0"
2235             if $count < 1;
2236            
2237             # Mean
2238 1 50       3 $mean = 0 unless defined $mean;
2239            
2240             # Standard deviation
2241 1 50       4 $sd = 1 unless defined $sd;
2242            
2243             # Random numbers(standard deviation)
2244 1         2 my @x1_elements;
2245            
2246 1         11 my $pi = $r->pi->value;
2247 1         6 for (1 .. $count) {
2248 100         253 my ($rand1, $rand2) = (rand, rand);
2249 100         210 while ($rand1 == 0) { $rand1 = rand(); }
  0         0  
2250            
2251 100         248 my $rnorm = ($sd * CORE::sqrt(-2 * CORE::log($rand1))
2252             * CORE::sin(2 * $pi * $rand2))
2253             + $mean;
2254            
2255 100         162 push @x1_elements, $rnorm;
2256             }
2257            
2258 1         976 return Rstats::Func::c_($r, @x1_elements);
2259             }
2260              
2261             sub round {
2262 7     7 0 9 my $r = shift;
2263            
2264 7 100       22 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2265 7         13 my ($_x1, $digits) = @_;
2266 7 100       17 $digits = $opt->{digits} unless defined $digits;
2267 7 100       16 $digits = 0 unless defined $digits;
2268            
2269 7         21 my $x1 = to_object($r, $_x1);
2270              
2271 7         19 my $ro = 10 ** $digits;
2272 7         8 my @x2_elements = map { Rstats::Func::c_double($r, Math::Round::round_even(Rstats::Func::value($r, $_) * $ro) / $ro) } @{Rstats::Func::decompose($r, $x1)};
  35         808  
  7         147  
2273 7         426 my $x2 = Rstats::Func::c_($r, @x2_elements);
2274 7         66 Rstats::Func::copy_attrs_to($r, $x1, $x2);
2275 7         156 Rstats::Func::mode($r, $x2, 'double');
2276            
2277 7         118 return $x2;
2278             }
2279              
2280             sub rowMeans {
2281 1     1 0 2 my $r = shift;
2282            
2283 1         2 my $x1 = shift;
2284            
2285 1         14 my $dim_values = Rstats::Func::dim($r, $x1)->values;
2286 1 50       9 if (@$dim_values == 2) {
2287 1         2 my $x1_values = [];
2288 1         5 for my $col (1 .. $dim_values->[1]) {
2289 3         5 my $x1_value = 0;
2290 3         20 $x1_value += $x1->value($_, $col) for (1 .. $dim_values->[0]);
2291 3         9 push @$x1_values, $x1_value / $dim_values->[0];
2292             }
2293 1         45 return Rstats::Func::c_($r, @$x1_values);
2294             }
2295             else {
2296 0         0 Carp::croak "Can't culculate rowMeans";
2297             }
2298             }
2299              
2300             sub rowSums {
2301 1     1 0 3 my $r = shift;
2302            
2303 1         2 my $x1 = shift;
2304            
2305 1         15 my $dim_values = Rstats::Func::dim($r, $x1)->values;
2306 1 50       8 if (@$dim_values == 2) {
2307 1         2 my $x1_values = [];
2308 1         5 for my $col (1 .. $dim_values->[1]) {
2309 3         6 my $x1_value = 0;
2310 3         19 $x1_value += $x1->value($_, $col) for (1 .. $dim_values->[0]);
2311 3         8 push @$x1_values, $x1_value;
2312             }
2313 1         34 return Rstats::Func::c_($r, @$x1_values);
2314             }
2315             else {
2316 0         0 Carp::croak "Can't culculate rowSums";
2317             }
2318             }
2319              
2320             # TODO: prob option
2321             sub sample {
2322 4     4 0 5 my $r = shift;
2323            
2324 4 100       14 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2325            
2326 4         6 my ($_x1, $length) = @_;
2327 4         11 my $x1 = to_object($r, $_x1);
2328            
2329             # Replace
2330 4         9 my $replace = $opt->{replace};
2331            
2332 4         18 my $x1_length = Rstats::Func::get_length($r, $x1);
2333 4 50       12 $length = $x1_length unless defined $length;
2334            
2335 4 50 66     15 Carp::croak "second argument element must be bigger than first argument elements count when you specify 'replace' option"
2336             if $length > $x1_length && !$replace;
2337            
2338 4         5 my @x2_elements;
2339 4         733 my $x1_elements = Rstats::Func::decompose($r, $x1);
2340 4         22 for my $i (0 .. $length - 1) {
2341 155         196 my $rand_num = int(rand @$x1_elements);
2342 155         194 my $rand_element = splice @$x1_elements, $rand_num, 1;
2343 155         194 push @x2_elements, $rand_element;
2344 155 100       348 push @$x1_elements, $rand_element if $replace;
2345             }
2346            
2347 4         808 return Rstats::Func::c_($r, @x2_elements);
2348             }
2349              
2350             sub sequence {
2351 1     1 0 3 my $r = shift;
2352            
2353 1         2 my $_x1 = shift;
2354            
2355 1         3 my $x1 = to_object($r, $_x1);
2356 1         6 my $x1_values = $x1->values;
2357            
2358 1         3 my @x2_values;
2359 1         3 for my $x1_value (@$x1_values) {
2360 3         6 push @x2_values, @{seq($r, 1, $x1_value)->values};
  3         8  
2361             }
2362            
2363 1         70 return Rstats::Func::c_($r, @x2_values);
2364             }
2365              
2366              
2367             sub tail {
2368 3     3 0 5 my $r = shift;
2369            
2370 3         11 my ($x1, $x_n) = Rstats::Func::args_array($r, ['x1', 'n'], @_);
2371            
2372 3 100       14 my $n = defined $x_n ? $x_n->value : 6;
2373            
2374 3         81 my $e1 = Rstats::Func::decompose($r, $x1);
2375 3 100       21 my $max = Rstats::Func::get_length($r, $x1) < $n ? Rstats::Func::get_length($r, $x1) : $n;
2376 3         4 my @e2;
2377 3         11 for (my $i = 0; $i < $max; $i++) {
2378 12         64 unshift @e2, $e1->[Rstats::Func::get_length($r, $x1) - ($i + 1)];
2379             }
2380            
2381 3         69 my $x2 = Rstats::Func::c_($r, @e2);
2382 3         20 Rstats::Func::copy_attrs_to($r, $x1, $x2);
2383            
2384 3         41 return $x2;
2385             }
2386              
2387             sub trunc {
2388 2     2 0 3 my $r = shift;
2389            
2390 2         4 my ($_x1) = @_;
2391            
2392 2         7 my $x1 = to_object($r, $_x1);
2393            
2394             my @x2_elements
2395 2         4 = map { Rstats::Func::c_double($r, int Rstats::Func::value($r, $_)) } @{Rstats::Func::decompose($r, $x1)};
  8         19  
  2         38  
2396              
2397 2         63 my $x2 = Rstats::Func::c_($r, @x2_elements);
2398 2         21 Rstats::Func::copy_attrs_to($r, $x1, $x2);
2399 2         46 Rstats::Func::mode($r, $x2, 'double');
2400            
2401 2         34 return $x2;
2402             }
2403              
2404             sub unique {
2405 79     79 0 114 my $r = shift;
2406            
2407 79         243 my $x1 = to_object($r, shift);
2408            
2409 79 100       753 if (Rstats::Func::is_vector($r, $x1)) {
2410 78         143 my $x2_elements = [];
2411 78         120 my $elements_count = {};
2412 78         106 my $na_count;
2413 78         103 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  78         2021  
2414 486 100       6151 if (Rstats::Func::is_na($r, $x1_element)) {
2415 3 100       10 unless ($na_count) {
2416 2         6 push @$x2_elements, $x1_element;
2417             }
2418 3         16 $na_count++;
2419             }
2420             else {
2421 483         966 my $str = Rstats::Func::to_string($r, $x1_element);
2422 483 100       1323 unless ($elements_count->{$str}) {
2423 392         702 push @$x2_elements, $x1_element;
2424             }
2425 483         2761 $elements_count->{$str}++;
2426             }
2427             }
2428              
2429 78         3175 return Rstats::Func::c_($r, @$x2_elements);
2430             }
2431             else {
2432 1         9 return $x1;
2433             }
2434             }
2435              
2436             sub median {
2437 2     2 0 3 my $r = shift;
2438            
2439 2         8 my $x1 = to_object($r, shift);
2440            
2441 2         7 my $x2 = unique($r, $x1);
2442 2         32 my $x3 = Rstats::Func::sort($r, $x2);
2443 2         31 my $x3_length = Rstats::Func::get_length($r, $x3);
2444            
2445 2 100       9 if ($x3_length % 2 == 0) {
2446 1         4 my $middle = $x3_length / 2;
2447 1         6 my $x4 = $x3->get($middle);
2448 1         8 my $x5 = $x3->get($middle + 1);
2449            
2450 1         6 return ($x4 + $x5) / 2;
2451             }
2452             else {
2453 1         5 my $middle = int($x3_length / 2) + 1;
2454 1         7 return $x3->get($middle);
2455             }
2456             }
2457              
2458             sub quantile {
2459 3     3 0 5 my $r = shift;
2460            
2461 3         11 my $x1 = to_object($r, shift);
2462            
2463 3         10 my $x2 = Rstats::Func::unique($r, $x1);
2464 3         319 my $x3 = Rstats::Func::sort($r, $x2);
2465 3         334 my $x3_length = Rstats::Func::get_length($r, $x3);
2466            
2467 3         7 my $quantile_elements = [];
2468            
2469             # Min
2470 3         22 push @$quantile_elements , $x3->get(1);
2471            
2472             # 1st quoter
2473 3 100       14 if ($x3_length % 4 == 0) {
2474 1         5 my $first_quoter = $x3_length * (1 / 4);
2475 1         6 my $x4 = $x3->get($first_quoter);
2476 1         9 my $x5 = $x3->get($first_quoter + 1);
2477            
2478 1         6 push @$quantile_elements, ((($x4 + $x5) / 2) + $x5) / 2;
2479             }
2480             else {
2481 2         9 my $first_quoter = int($x3_length * (1 / 4)) + 1;
2482 2         14 push @$quantile_elements, $x3->get($first_quoter);
2483             }
2484            
2485             # middle
2486 3 100       34 if ($x3_length % 2 == 0) {
2487 1         4 my $middle = $x3_length / 2;
2488 1         7 my $x4 = $x3->get($middle);
2489 1         8 my $x5 = $x3->get($middle + 1);
2490            
2491 1         5 push @$quantile_elements, (($x4 + $x5) / 2);
2492             }
2493             else {
2494 2         7 my $middle = int($x3_length / 2) + 1;
2495 2         13 push @$quantile_elements, $x3->get($middle);
2496             }
2497            
2498             # 3rd quoter
2499 3 100       23 if ($x3_length % 4 == 0) {
2500 1         3 my $third_quoter = $x3_length * (3 / 4);
2501 1         7 my $x4 = $x3->get($third_quoter);
2502 1         8 my $x5 = $x3->get($third_quoter + 1);
2503            
2504 1         6 push @$quantile_elements, (($x4 + (($x4 + $x5) / 2)) / 2);
2505             }
2506             else {
2507 2         9 my $third_quoter = int($x3_length * (3 / 4)) + 1;
2508 2         12 push @$quantile_elements, $x3->get($third_quoter);
2509             }
2510            
2511             # Max
2512 3         39 push @$quantile_elements , $x3->get($x3_length);
2513            
2514 3         83 my $x4 = Rstats::Func::c_($r, @$quantile_elements);
2515 3         219 Rstats::Func::names($r, $x4, Rstats::Func::c_($r, qw/0% 25% 50% 75% 100%/));
2516            
2517 3         120 return $x4;
2518             }
2519              
2520             sub sd {
2521 0     0 0 0 my $r = shift;
2522            
2523 0         0 my $x1 = to_object($r, shift);
2524            
2525 0         0 my $sd = Rstats::Func::sqrt($r, var($r, $x1));
2526            
2527 0         0 return $sd;
2528             }
2529              
2530             sub var {
2531 1     1 0 3 my $r = shift;
2532            
2533 1         4 my $x1 = to_object($r, shift);
2534            
2535 1         5 my $var = sum($r, ($x1 - Rstats::Func::mean($r, $x1)) ** 2) / (Rstats::Func::get_length($r, $x1) - 1);
2536            
2537 1         32 return $var;
2538             }
2539              
2540             sub which {
2541 1     1 0 4 my $r = shift;
2542            
2543 1         3 my ($_x1, $cond_cb) = @_;
2544            
2545 1         5 my $x1 = to_object($r, $_x1);
2546 1         10 my $x1_values = $x1->values;
2547 1         3 my @x2_values;
2548 1         4 for (my $i = 0; $i < @$x1_values; $i++) {
2549 3         11 local $_ = $x1_values->[$i];
2550 3 100       8 if ($cond_cb->($x1_values->[$i])) {
2551 2         15 push @x2_values, $i + 1;
2552             }
2553             }
2554            
2555 1         28 return Rstats::Func::c_($r, @x2_values);
2556             }
2557              
2558             sub inner_product {
2559 4     4 0 6 my $r = shift;
2560            
2561 4         7 my ($x1, $x2) = @_;
2562            
2563 4 100 100     50 if (Rstats::Func::is_null($r, $x1) || Rstats::Func::is_null($r, $x2)) {
2564 2         217 Carp::croak "requires numeric/complex matrix/vector arguments";
2565             }
2566            
2567             # Convert to matrix
2568 2 50       28 $x1 = Rstats::Func::t($r, Rstats::Func::as_matrix($r, $x1))
2569             if Rstats::Func::is_vector($r, $x1);
2570 2 50       30 $x2 = Rstats::Func::as_matrix($r, $x2) if Rstats::Func::is_vector($r, $x2);
2571            
2572             # Calculate
2573 2 50 33     35 if (Rstats::Func::is_matrix($r, $x1) && Rstats::Func::is_matrix($r, $x2)) {
2574            
2575 2 50 33     24 Carp::croak "requires numeric/complex matrix/vector arguments"
2576             if Rstats::Func::get_length($r, $x1) == 0 || Rstats::Func::get_length($r, $x2) == 0;
2577 2 100       25 Carp::croak "Error in a x b : non-conformable arguments"
2578             unless Rstats::Func::dim($r, $x1)->values->[1] == Rstats::Func::dim($r, $x2)->values->[0];
2579            
2580 1         19 my $row_max = Rstats::Func::dim($r, $x1)->values->[0];
2581 1         16 my $col_max = Rstats::Func::dim($r, $x2)->values->[1];
2582            
2583 1         6 my $x3_elements = [];
2584 1         5 for (my $col = 1; $col <= $col_max; $col++) {
2585 1         5 for (my $row = 1; $row <= $row_max; $row++) {
2586 1         4 my $x1_part = Rstats::Func::get($r, $x1, $row);
2587 1         6 my $x2_part = Rstats::Func::get($r, $x2, Rstats::Func::NULL($r), $col);
2588 1         6 my $x3_part = sum($r, $x1 * $x2);
2589 1         18 push @$x3_elements, $x3_part;
2590             }
2591             }
2592            
2593 1         16 my $x3 = Rstats::Func::matrix($r, c_($r, @$x3_elements), $row_max, $col_max);
2594            
2595 1         17 return $x3;
2596             }
2597             else {
2598 0         0 Carp::croak "inner_product should be dim < 3."
2599             }
2600             }
2601              
2602             sub row {
2603 1     1 0 4 my $r = shift;
2604            
2605 1         2 my $x1 = shift;
2606            
2607 1         5 my $nrow = Rstats::Func::nrow($r, $x1)->value;
2608 1         15 my $ncol = Rstats::Func::ncol($r, $x1)->value;
2609            
2610 1         18 my @values = (1 .. $nrow) x $ncol;
2611            
2612 1         236 return Rstats::Func::array($r, Rstats::Func::c_($r, @values), Rstats::Func::c_($r, $nrow, $ncol));
2613             }
2614              
2615              
2616              
2617             sub ncol {
2618 5     5 0 11 my $r = shift;
2619            
2620 5         10 my $x1 = shift;
2621            
2622 5 100       55 if (Rstats::Func::is_data_frame($r, $x1)) {
    100          
2623 1         23 return Rstats::Func::c_($r, Rstats::Func::get_length($r, $x1));
2624             }
2625             elsif (Rstats::Func::is_list($r, $x1)) {
2626 1         9 return Rstats::Func::NULL($r);
2627             }
2628             else {
2629 3         37 return Rstats::Func::c_($r, Rstats::Func::dim($r, $x1)->values->[1]);
2630             }
2631             }
2632              
2633             sub seq {
2634 139     139 0 215 my $r = shift;
2635            
2636             # Option
2637 139 100       452 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2638            
2639             # Along
2640 139         266 my $_along = $opt->{along};
2641 139 100       314 if (defined $_along) {
2642 1         4 my $along = to_object($r, $_along);
2643 1         5 my $length = Rstats::Func::get_length($r, $along);
2644 1         6 return seq($r, 1, $length);
2645             }
2646             else {
2647 138         268 my ($from, $to) = @_;
2648            
2649             # From
2650 138 100       392 $from = $opt->{from} unless defined $from;
2651 138 50       307 Carp::croak "seq function need from option" unless defined $from;
2652            
2653             # To
2654 138 100       363 $to = $opt->{to} unless defined $to;
2655 138 50       284 Carp::croak "seq function need to option" unless defined $to;
2656              
2657             # Length
2658 138         229 my $length = $opt->{length};
2659            
2660             # By
2661 138         203 my $by = $opt->{by};
2662            
2663 138 50 66     401 if (defined $length && defined $by) {
2664 0         0 Carp::croak "Can't use by option and length option as same time";
2665             }
2666            
2667 138 100       303 unless (defined $by) {
2668 135 100       345 if ($to >= $from) {
2669 134         203 $by = 1;
2670             }
2671             else {
2672 1         2 $by = -1;
2673             }
2674             }
2675 138 50       330 Carp::croak "by option should be except for 0" if $by == 0;
2676            
2677 138 50       312 $to = $from unless defined $to;
2678            
2679 138 100 66     361 if (defined $length && $from ne $to) {
2680 1         4 $by = ($to - $from) / ($length - 1);
2681             }
2682            
2683 138         225 my $elements = [];
2684 138 100       435 if ($to == $from) {
    100          
2685 2         5 $elements->[0] = $to;
2686             }
2687             elsif ($to > $from) {
2688 134 50       314 if ($by < 0) {
2689 0         0 Carp::croak "by option is invalid number(seq function)";
2690             }
2691            
2692 134         192 my $element = $from;
2693 134         319 while ($element <= $to) {
2694 2422         3343 push @$elements, $element;
2695 2422         4690 $element += $by;
2696             }
2697             }
2698             else {
2699 2 50       7 if ($by > 0) {
2700 0         0 Carp::croak "by option is invalid number(seq function)";
2701             }
2702            
2703 2         3 my $element = $from;
2704 2         7 while ($element >= $to) {
2705 8         12 push @$elements, $element;
2706 8         18 $element += $by;
2707             }
2708             }
2709            
2710 138         18654 return Rstats::Func::c_($r, @$elements);
2711             }
2712             }
2713              
2714             sub numeric {
2715 1     1 0 2 my $r = shift;
2716            
2717 1         2 my $num = shift;
2718            
2719 1         36 return Rstats::Func::c_($r, (0) x $num);
2720             }
2721              
2722             sub _fix_pos {
2723 1137     1137   1676 my $r = shift;
2724            
2725 1137         1929 my ($data1, $datx2, $reverse) = @_;
2726            
2727 1137         1279 my $x1;
2728             my $x2;
2729 1137 100       2296 if (ref $datx2) {
2730 904         1110 $x1 = $data1;
2731 904         1214 $x2 = $datx2;
2732             }
2733             else {
2734 233 100       452 if ($reverse) {
2735 212         3638 $x1 = Rstats::Func::c_($r, $datx2);
2736 212         1173 $x2 = $data1;
2737             }
2738             else {
2739 21         30 $x1 = $data1;
2740 21         373 $x2 = Rstats::Func::c_($r, $datx2);
2741             }
2742             }
2743            
2744 1137         31244 return ($x1, $x2);
2745             }
2746              
2747             sub bool {
2748 32978     32978 0 42412 my $r = shift;
2749            
2750 32978         40426 my $x1 = shift;
2751            
2752 32978         137778 my $length = Rstats::Func::get_length($r, $x1);
2753 32978 100       96897 if ($length == 0) {
    100          
2754 1         101 Carp::croak 'Error in if (a) { : argument is of length zero';
2755             }
2756             elsif ($length > 1) {
2757 1         178 Carp::carp 'In if (a) { : the condition has length > 1 and only the first element will be used';
2758             }
2759            
2760 32977         158415 my $type = $x1->get_type;
2761 32977         157248 my $value = $x1->value;
2762              
2763 32977         47039 my $is;
2764 32977 50 33     248727 if ($type eq 'character' || $type eq 'complex') {
    100 66        
    50          
2765 0         0 Carp::croak 'Error in -a : invalid argument to unary operator ';
2766             }
2767             elsif ($type eq 'double') {
2768 3 50 33     28 if ($value eq 'Inf' || $value eq '-Inf') {
    50          
2769 0         0 $is = 1;
2770             }
2771             elsif ($value eq 'NaN') {
2772 0         0 Carp::croak 'argument is not interpretable as logical';
2773             }
2774             else {
2775 3         6 $is = $value;
2776             }
2777             }
2778             elsif ($type eq 'integer' || $type eq 'logical') {
2779 32974         44254 $is = $value;
2780             }
2781             else {
2782 0         0 Carp::croak "Invalid type";
2783             }
2784            
2785 32977 50       62104 if (!defined $value) {
2786 0         0 Carp::croak "Error in bool context (a) { : missing value where TRUE/FALSE needed"
2787             }
2788              
2789 32977         181551 return $is;
2790             }
2791              
2792             sub set {
2793 58     58 0 101 my ($r, $x1) = @_;
2794            
2795 58 100 100     394 if ($x1->{object_type} eq 'NULL' || $x1->{object_type} eq 'array' || $x1->{object_type} eq 'factor') {
    100 66        
    50          
2796 50         116 return Rstats::Func::set_array(@_);
2797             }
2798             elsif ($x1->{object_type} eq 'list') {
2799 6         16 return Rstats::Func::set_list(@_);
2800             }
2801             elsif ($x1->{object_type} eq 'data.frame') {
2802 2         8 return Rstats::Func::set_dataframe(@_);
2803             }
2804             else {
2805 0         0 croak "Error in set() : Not implemented";
2806             }
2807             }
2808              
2809              
2810              
2811             sub get_array {
2812 998     998 0 1393 my $r = shift;
2813            
2814 998         1290 my $x1 = shift;
2815            
2816 998 100       2462 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2817 998         1408 my $dim_drop;
2818             my $level_drop;
2819 998 100       34402 if (Rstats::Func::is_factor($r, $x1)) {
2820 12         26 $level_drop = $opt->{drop};
2821             }
2822             else {
2823 986         1741 $dim_drop = $opt->{drop};
2824             }
2825            
2826 998 100       13765 $dim_drop = 1 unless defined $dim_drop;
2827 998 100       2172 $level_drop = 0 unless defined $level_drop;
2828            
2829 998         2458 my @_indexs = @_;
2830              
2831 998         1162 my $_indexs;
2832 998 50       2074 if (@_indexs) {
2833 998         1696 $_indexs = \@_indexs;
2834             }
2835             else {
2836 0         0 my $at = $x1->at;
2837 0 0       0 $_indexs = ref $at eq 'ARRAY' ? $at : [$at];
2838             }
2839 998         5135 $x1->at($_indexs);
2840            
2841 998         1426 my ($poss, $x2_dim, $new_indexes) = @{Rstats::Util::parse_index($r, $x1, $dim_drop, $_indexs)};
  998         2885  
2842            
2843 998         5453 my $x1_values = $x1->values;
2844 998         2204 my @x2_values = map { $x1_values->[$_] } @$poss;
  1146         3045  
2845            
2846             # array
2847 998         1411 my $x_matrix;
2848 998 100       5032 if ($x1->get_type eq "character") {
    50          
    100          
    50          
    0          
2849 24         203 $x_matrix = c_character($r, \@x2_values);
2850             }
2851             elsif ($x1->get_type eq "complex") {
2852 0         0 $x_matrix = c_complex($r, \@x2_values);
2853             }
2854             elsif ($x1->get_type eq "double") {
2855 962         12320 $x_matrix = c_double($r, \@x2_values);
2856             }
2857             elsif ($x1->get_type eq "integer") {
2858 12         96 $x_matrix = c_integer($r, \@x2_values);
2859             }
2860             elsif ($x1->get_type eq "logical") {
2861 0         0 $x_matrix = c_logical($r, \@x2_values);
2862             }
2863             else {
2864 0         0 croak("Invalid type " . $x1->get_type . " is passed");
2865             }
2866            
2867 998         59044 my $x2 = Rstats::Func::array(
2868             $r,
2869             $x_matrix,
2870             Rstats::Func::c_($r, @$x2_dim)
2871             );
2872            
2873             # Copy attributes
2874 998         18886 Rstats::Func::copy_attrs_to($r, $x1, $x2, {new_indexes => $new_indexes, exclude => ['dim']});
2875              
2876             # level drop
2877 998 100       3418 if ($level_drop) {
2878 1         99 my $p = Rstats::Func::as_character($r, $x2);
2879 1         75 $x2 = Rstats::Func::factor($r, Rstats::Func::as_character($r, $x2));
2880             }
2881            
2882 998         21468 return $x2;
2883             }
2884              
2885 0     0 0 0 sub getin_array { get(@_) }
2886              
2887             sub to_string_array {
2888 560     560 0 825 my $r = shift;
2889            
2890 560         690 my $x1 = shift;
2891            
2892 560         9991 my $is_factor = Rstats::Func::is_factor($r, $x1);
2893 560         11595 my $is_ordered = Rstats::Func::is_ordered($r, $x1);
2894 560         3209 my $levels;
2895 560 100       1760 if ($is_factor) {
2896 4         56 $levels = Rstats::Func::levels($r, $x1)->values;
2897             }
2898            
2899 560 100       10699 $x1 = Rstats::Func::as_character($r, $x1) if Rstats::Func::is_factor($r, $x1);
2900            
2901 560         7445 my $is_character = Rstats::Func::is_character($r, $x1);
2902              
2903 560         2734 my $values = $x1->values;
2904 560         2818 my $type = $x1->get_type;
2905            
2906 560         2760 my $dim_values = $x1->dim_as_array->values;
2907            
2908 560         2700 my $dim_length = @$dim_values;
2909 560         850 my $dim_num = $dim_length - 1;
2910 560         841 my $poss = [];
2911            
2912 560         695 my $str;
2913 560 50       1102 if (@$values) {
2914 560 100       981 if ($dim_length == 1) {
    100          
2915 550         4412 my $names = Rstats::Func::names($r, $x1)->values;
2916 550 100       1955 if (@$names) {
2917 1         5 $str .= join(' ', @$names) . "\n";
2918             }
2919 550         950 my @parts = map { Rstats::Func::_value_to_string($r, $x1, $_, $type, $is_factor) } @$values;
  618         1299  
2920 550         1752 $str .= '[1] ' . join(' ', @parts) . "\n";
2921             }
2922             elsif ($dim_length == 2) {
2923 7         13 $str .= ' ';
2924            
2925 7         29 my $colnames = Rstats::Func::colnames($r, $x1)->values;
2926 7 100       30 if (@$colnames) {
2927 1         5 $str .= join(' ', @$colnames) . "\n";
2928             }
2929             else {
2930 6         45 for my $d2 (1 .. $dim_values->[1]) {
2931 12 100       50 $str .= $d2 == $dim_values->[1] ? "[,$d2]\n" : "[,$d2] ";
2932             }
2933             }
2934            
2935 7         22 my $rownames = Rstats::Func::rownames($r, $x1)->values;
2936 7 100       40 my $use_rownames = @$rownames ? 1 : 0;
2937 7         21 for my $d1 (1 .. $dim_values->[0]) {
2938 46 100       81 if ($use_rownames) {
2939 2         5 my $rowname = $rownames->[$d1 - 1];
2940 2         5 $str .= "$rowname ";
2941             }
2942             else {
2943 44         86 $str .= "[$d1,] ";
2944             }
2945            
2946 46         51 my @parts;
2947 46         101 for my $d2 (1 .. $dim_values->[1]) {
2948 74         404 my $part = $x1->value($d1, $d2);
2949 74         191 push @parts, Rstats::Func::_value_to_string($r, $x1, $part, $type, $is_factor);
2950             }
2951            
2952 46         157 $str .= join(' ', @parts) . "\n";
2953             }
2954             }
2955             else {
2956 3         4 my $code;
2957             $code = sub {
2958 5     5   13 my (@dim_values) = @_;
2959 5         9 my $dim_value = pop @dim_values;
2960            
2961 5         17 for (my $i = 1; $i <= $dim_value; $i++) {
2962 12         45 $str .= (',' x $dim_num) . "$i" . "\n";
2963 12         27 unshift @$poss, $i;
2964 12 100       28 if (@dim_values > 2) {
2965 2         3 $dim_num--;
2966 2         11 $code->(@dim_values);
2967 2         4 $dim_num++;
2968             }
2969             else {
2970 10         17 $str .= ' ';
2971            
2972 10         36 my $l_dimnames = Rstats::Func::dimnames($r, $x1);
2973 10         19 my $dimnames;
2974 10 50       93 if (Rstats::Func::is_null($r, $l_dimnames)) {
2975 10         19 $dimnames = [];
2976             }
2977             else {
2978 0         0 my $x_dimnames = $l_dimnames->getin($i);
2979 0 0       0 $dimnames = defined $l_dimnames ? $l_dimnames->values : [];
2980             }
2981            
2982 10 50       61 if (@$dimnames) {
2983 0         0 $str .= join(' ', @$dimnames) . "\n";
2984             }
2985             else {
2986 10         33 for my $d2 (1 .. $dim_values[1]) {
2987 36 100       113 $str .= $d2 == $dim_values[1] ? "[,$d2]\n" : "[,$d2] ";
2988             }
2989             }
2990              
2991 10         23 for my $d1 (1 .. $dim_values[0]) {
2992 46         149 $str .= "[$d1,] ";
2993            
2994 46         50 my @parts;
2995 46         110 for my $d2 (1 .. $dim_values[1]) {
2996 168         971 my $part = $x1->value($d1, $d2, @$poss);
2997 168         526 push @parts, Rstats::Func::_value_to_string($r, $x1, $part, $type, $is_factor);
2998             }
2999            
3000 46         230 $str .= join(' ', @parts) . "\n";
3001             }
3002             }
3003 12         59 shift @$poss;
3004             }
3005 3         25 };
3006 3         9 $code->(@$dim_values);
3007             }
3008              
3009 560 100       1630 if ($is_factor) {
3010 4 100       12 if ($is_ordered) {
3011 1         6 $str .= 'Levels: ' . join(' < ', @$levels) . "\n";
3012             }
3013             else {
3014 3         20 $str .= 'Levels: ' . join(' ', , @$levels) . "\n";
3015             }
3016             }
3017             }
3018             else {
3019 0         0 $str = 'NULL';
3020             }
3021            
3022 560         5350 return $str;
3023             }
3024              
3025             sub _value_to_string {
3026 908     908   1223 my $r = shift;
3027            
3028 908         1712 my ($x1, $value, $type, $is_factor) = @_;
3029            
3030 908         999 my $string;
3031 908 100       2777 if ($is_factor) {
3032 24 100       47 if (!defined $value) {
3033 2         3 $string = '';
3034             }
3035             else {
3036 22         59 $string = "$value";
3037             }
3038             }
3039             else {
3040 884 100       3247 if (!defined $value) {
    100          
    100          
    100          
3041 1         3 $string = 'NA';
3042             }
3043             elsif ($type eq 'complex') {
3044 5   50     23 my $re = $value->{re} || 0;
3045 5   100     25 my $im = $value->{im} || 0;
3046 5         27 $string = "$re";
3047 5 100       18 $string .= $im >= 0 ? "+$im" : $im;
3048 5         9 $string .= 'i';
3049             }
3050             elsif ($type eq 'character') {
3051 291         641 $string = '"' . $value . '"';
3052             }
3053             elsif ($type eq 'logical') {
3054 9 100       27 $string = $value ? 'TRUE' : 'FALSE';
3055             }
3056             else {
3057 578         2458 $string = "$value";
3058             }
3059             }
3060            
3061 908         3553 return $string;
3062             }
3063              
3064             sub str {
3065 11     11 0 15 my $r = shift;
3066            
3067 11         16 my $x1 = shift;
3068            
3069 11         14 my @str;
3070            
3071 11 50 66     102 if (Rstats::Func::is_null($r, $x1)) {
    50          
3072 0         0 push @str, "NULL";
3073             }
3074             elsif (Rstats::Func::is_vector($r, $x1) || is_array($r, $x1)) {
3075             # Short type
3076 11         54 my $type = $x1->get_type;
3077 11         14 my $short_type;
3078 11 100       48 if ($type eq 'character') {
    100          
    100          
    100          
    50          
3079 1         3 $short_type = 'chr';
3080             }
3081             elsif ($type eq 'complex') {
3082 1         3 $short_type = 'cplx';
3083             }
3084             elsif ($type eq 'double') {
3085 7         9 $short_type = 'num';
3086             }
3087             elsif ($type eq 'integer') {
3088 1         3 $short_type = 'int';
3089             }
3090             elsif ($type eq 'logical') {
3091 1         2 $short_type = 'logi';
3092             }
3093             else {
3094 0         0 $short_type = 'Unkonown';
3095             }
3096 11         19 push @str, $short_type;
3097            
3098             # Dimention
3099 11         13 my @dim_str;
3100 11         48 my $length = Rstats::Func::get_length($r, $x1);
3101 11 100       29 if (exists $x1->{dim}) {
3102 3         16 my $dim_values = $x1->{dim}->values;
3103 3         22 for (my $i = 0; $i < $x1->{dim}->get_length; $i++) {
3104 4         7 my $d = $dim_values->[$i];
3105 4         5 my $d_str;
3106 4 100       10 if ($d == 1) {
3107 1         2 $d_str = "1";
3108             }
3109             else {
3110 3         7 $d_str = "1:$d";
3111             }
3112            
3113 4 100       21 if ($x1->{dim}->get_length == 1) {
3114 2         6 $d_str .= "(" . ($i + 1) . "d)";
3115             }
3116 4         25 push @dim_str, $d_str;
3117             }
3118             }
3119             else {
3120 8 100       21 if ($length != 1) {
3121 7         18 push @dim_str, "1:$length";
3122             }
3123             }
3124 11 100       28 if (@dim_str) {
3125 10         18 my $dim_str = join(', ', @dim_str);
3126 10         23 push @str, "[$dim_str]";
3127             }
3128            
3129             # Vector
3130 11         14 my @element_str;
3131 11 100       22 my $max_count = $length > 10 ? 10 : $length;
3132 11         77 my $is_character = is_character($r, $x1);
3133 11         53 my $values = $x1->values;
3134 11         36 for (my $i = 0; $i < $max_count; $i++) {
3135 48         107 push @element_str, Rstats::Func::_value_to_string($r, $x1, $values->[$i], $type);
3136             }
3137 11 100       21 if ($length > 10) {
3138 2         4 push @element_str, '...';
3139             }
3140 11         25 my $element_str = join(' ', @element_str);
3141 11         69 push @str, $element_str;
3142             }
3143            
3144 11         80 my $str = join(' ', @str);
3145            
3146 11         56 return $str;
3147             }
3148              
3149             sub at {
3150 1370     1370 0 1910 my $r = shift;
3151            
3152 1370         1871 my $x1 = shift;
3153            
3154 1370 100       3071 if (@_) {
3155 1312         3418 $x1->{at} = [@_];
3156            
3157 1312         3790 return $x1;
3158             }
3159            
3160 58         159 return $x1->{at};
3161             }
3162              
3163             sub _name_to_index {
3164 31     31   56 my $r = shift;
3165 31         41 my $x1 = shift;
3166 31         107 my $x1_index = Rstats::Func::to_object($r, shift);
3167            
3168 31         150 my $e1_name = $x1_index->value;
3169 31         56 my $found;
3170 31         351 my $names = Rstats::Func::names($r, $x1)->values;
3171 31         146 my $index;
3172 31         91 for (my $i = 0; $i < @$names; $i++) {
3173 55         82 my $name = $names->[$i];
3174 55 100       159 if ($e1_name eq $name) {
3175 31         68 $index = $i + 1;
3176 31         33 $found = 1;
3177 31         57 last;
3178             }
3179             }
3180 31 50       67 croak "Not found $e1_name" unless $found;
3181            
3182 31         96 return $index;
3183             }
3184              
3185             sub nlevels {
3186 2     2 0 5 my $r = shift;
3187            
3188 2         3 my $x1 = shift;
3189            
3190 2         67 return Rstats::Func::c_($r, Rstats::Func::get_length($r, Rstats::Func::levels($r, $x1)));
3191             }
3192              
3193             sub getin_list {
3194 256     256 0 385 my ($r, $x1, $_index) = @_;
3195            
3196 256 50       499 unless (defined $_index) {
3197 0         0 $_index = $x1->at;
3198             }
3199 256         1197 $x1->at($_index);
3200            
3201 256         2022 my $x1_index = Rstats::Func::to_object($r, $_index);
3202 256         381 my $index;
3203 256 100       2160 if (Rstats::Func::is_character($r, $x1_index)) {
3204 25         64 $index = Rstats::Func::_name_to_index($r, $x1, $x1_index);
3205             }
3206             else {
3207 231         1128 $index = $x1_index->values->[0];
3208             }
3209 256         6466 my $elements = $x1->list;
3210 256         1621 my $element = $elements->[$index - 1];
3211            
3212 256         2103 return $element;
3213             }
3214              
3215             sub get_list {
3216 3     3 0 4 my $r = shift;
3217 3         5 my $x1 = shift;
3218 3         14 my $x_index = Rstats::Func::to_object($r, shift);
3219            
3220 3         62 my $elements = $x1->list;
3221            
3222 3         18 my $class = ref $x1;
3223 3         17 my $list = Rstats::Func::list($r);;
3224 3         68 my $list_elements = $list->list;
3225            
3226 3         77 my $index_values;
3227 3 100       29 if (Rstats::Func::is_character($r, $x_index)) {
3228 1         2 $index_values = [];
3229 1         2 for my $value (@{$x_index->values}) {
  1         6  
3230 2         7 push @$index_values, Rstats::Func::_name_to_index($r, $x1, $value);
3231             }
3232             }
3233             else {
3234 2         12 $index_values = $x_index->values;
3235             }
3236 3         14 for my $i (@{$index_values}) {
  3         9  
3237 5         15 push @$list_elements, $elements->[$i - 1];
3238             }
3239            
3240             Rstats::Func::copy_attrs_to(
3241 3         136 $r, $x1, $list, {new_indexes => [Rstats::Func::c_($r, @$index_values)]}
3242             );
3243              
3244 3         41 return $list;
3245             }
3246              
3247             sub set_list {
3248 8     8 0 14 my $r = shift;
3249 8         13 my ($x1, $v1) = @_;
3250            
3251 8         42 my $_index = $x1->at;
3252 8         62 my $x1_index = Rstats::Func::to_object($r, @$_index);
3253 8         14 my $index;
3254 8 100       69 if (Rstats::Func::is_character($r, $x1_index)) {
3255 1         3 $index = Rstats::Func::_name_to_index($r, $x1, $x1_index);
3256             }
3257             else {
3258 7         38 $index = $x1_index->values->[0];
3259             }
3260 8         69 $v1 = Rstats::Func::to_object($r, $v1);
3261            
3262 8 100       68 if (Rstats::Func::is_null($r, $v1)) {
3263 3         7 splice @{$x1->list}, $index - 1, 1;
  3         65  
3264 3 100       37 if (exists $x1->{names}) {
3265 2         12 my $new_names_values = $x1->{names}->values;
3266 2         7 splice @$new_names_values, $index - 1, 1;
3267 2         26 $x1->{names} = Rstats::Func::c_character($r, @$new_names_values);
3268             }
3269            
3270 3 100       19 if (exists $x1->{dimnames}) {
3271 2         14 my $new_dimname_values = $x1->{dimnames}[1]->values;
3272 2         6 splice @$new_dimname_values, $index - 1, 1;
3273 2         32 $x1->{dimnames}[1] = Rstats::Func::c_character($r, @$new_dimname_values);
3274             }
3275             }
3276             else {
3277 5 100       47 if (Rstats::Func::is_data_frame($r, $x1)) {
3278 1         7 my $x1_length = $x1->get_length;
3279 1         6 my $v1_length = $v1->get_length;
3280 1 50       6 if ($x1_length != $v1_length) {
3281 0         0 croak "Error in data_frame set: replacement has $v1_length rows, data has $x1_length";
3282             }
3283             }
3284            
3285 5         134 $x1->list->[$index - 1] = $v1;
3286             }
3287            
3288 8         103 return $x1;
3289             }
3290              
3291             sub to_string_list {
3292 3     3 0 4 my $r = shift;
3293 3         5 my $x1 = shift;
3294            
3295 3         4 my $poses = [];
3296 3         5 my $str = '';
3297 3         7 _to_string_list($r, $x1, $poses, \$str);
3298            
3299 3         22 return $str;
3300             }
3301              
3302             sub _to_string_list {
3303 4     4   7 my ($r, $list, $poses, $str_ref) = @_;
3304            
3305 4         84 my $elements = $list->list;
3306 4         30 for (my $i = 0; $i < @$elements; $i++) {
3307 8         14 push @$poses, $i + 1;
3308 8         17 $$str_ref .= join('', map { "[[$_]]" } @$poses) . "\n";
  10         35  
3309            
3310 8         14 my $element = $elements->[$i];
3311 8 100       18 if ($element->{object_type} eq 'list') {
3312 1         6 _to_string_list($r, $element, $poses, $str_ref);
3313             }
3314             else {
3315 7         24 $$str_ref .= Rstats::Func::to_string($r, $element) . "\n";
3316             }
3317 8         32 pop @$poses;
3318             }
3319             }
3320              
3321 2     2 0 8 sub set_dataframe { Rstats::Func::set_list(@_) }
3322              
3323 115     115 0 235 sub getin_dataframe { Rstats::Func::getin_list(@_) }
3324              
3325             sub get_dataframe {
3326 16     16 0 25 my $r = shift;
3327            
3328 16         24 my $x1 = shift;
3329 16         26 my $_row_index = shift;
3330 16         27 my $_col_index = shift;
3331            
3332             # Fix column index and row index
3333 16 100       53 unless (defined $_col_index) {
3334 3         4 $_col_index = $_row_index;
3335 3         17 $_row_index = Rstats::Func::NULL($r);
3336             }
3337 16         52 my $row_index = Rstats::Func::to_object($r, $_row_index);
3338 16         45 my $col_index = Rstats::Func::to_object($r, $_col_index);
3339            
3340             # Convert name index to number index
3341 16         21 my $col_index_values;
3342 16 100       148 if (Rstats::Func::is_null($r, $col_index)) {
    100          
    100          
3343 7         96 $col_index_values = [1 .. Rstats::Func::names($r, $x1)->get_length];
3344             }
3345             elsif (Rstats::Func::is_character($r, $col_index)) {
3346 2         5 $col_index_values = [];
3347 2         6 for my $col_index_value (@{$col_index->values}) {
  2         13  
3348 3         9 push @$col_index_values, Rstats::Func::_name_to_index($r, $x1, $col_index_value);
3349             }
3350             }
3351             elsif (Rstats::Func::is_logical($r, $col_index)) {
3352 2         13 my $tmp_col_index_values = $col_index->values;
3353 2         10 for (my $i = 0; $i < @$tmp_col_index_values; $i++) {
3354 6 100       26 push @$col_index_values, $i + 1 if $tmp_col_index_values->[$i];
3355             }
3356             }
3357             else {
3358 5         27 my $col_index_values_tmp = $col_index->values;
3359            
3360 5 100       20 if ($col_index_values_tmp->[0] < 0) {
3361 1         3 my $delete_col_index_values_h = {};
3362 1         3 for my $index (@$col_index_values_tmp) {
3363 2 50       6 croak "Can't contain both plus and minus index" if $index > 0;
3364 2         7 $delete_col_index_values_h->{-$index} = 1;
3365             }
3366            
3367 1         3 $col_index_values = [];
3368 1         15 for (my $index = 1; $index <= Rstats::Func::names($r, $x1)->get_length; $index++) {
3369 3 100       50 push @$col_index_values, $index unless $delete_col_index_values_h->{$index};
3370             }
3371             }
3372             else {
3373 4         7 $col_index_values = $col_index_values_tmp;
3374             }
3375             }
3376            
3377             # Extract columns
3378 16         437 my $elements = $x1->list;
3379 16         102 my $new_elements = [];
3380 16         32 for my $i (@{$col_index_values}) {
  16         35  
3381 35         80 push @$new_elements, $elements->[$i - 1];
3382             }
3383            
3384             # Extract rows
3385 16         30 for my $new_element (@$new_elements) {
3386 35 100       291 $new_element = $new_element->get($row_index)
3387             unless Rstats::Func::is_null($r, $row_index);
3388             }
3389            
3390             # Create new data frame
3391 16         85 my $data_frame = Rstats::Func::new_data_frame($r);;
3392 16         397 $data_frame->list($new_elements);
3393 16         1510 Rstats::Func::copy_attrs_to(
3394             $r,
3395             $x1,
3396             $data_frame,
3397             {new_indexes => [$row_index, Rstats::Func::c_($r, @$col_index_values)]}
3398             );
3399 16         254 $data_frame->{dimnames}[0] = Rstats::Func::c_character($r,
3400             1 .. Rstats::Func::getin_dataframe($r, $data_frame, 1)->get_length
3401             );
3402            
3403 16         166 return $data_frame;
3404             }
3405              
3406             sub to_string_dataframe {
3407 1     1 0 2 my $r = shift;
3408            
3409 1         2 my $x1 = shift;
3410              
3411 1         14 my $t = Text::UnicodeTable::Simple->new(border => 0, alignment => 'right');
3412            
3413             # Names
3414 1         45 my $column_names = Rstats::Func::names($r, $x1)->values;
3415 1         10 $t->set_header('', @$column_names);
3416            
3417             # columns
3418 1         168 my $columns = [];
3419 1         6 for (my $i = 1; $i <= @$column_names; $i++) {
3420 2         12 my $x = $x1->getin($i);
3421 2 100       37 $x = Rstats::Func::as_character($r, $x) if Rstats::Func::is_factor($r, $x);
3422 2         32 push @$columns, $x->values;
3423             }
3424 1         3 my $col_count = @{$columns};
  1         2  
3425 1         9 my $row_count = @{$columns->[0]};
  1         3  
3426            
3427 1         5 for (my $i = 0; $i < $row_count; $i++) {
3428 3         268 my @row;
3429 3         7 push @row, $i + 1;
3430 3         8 for (my $k = 0; $k < $col_count; $k++) {
3431 6         17 push @row, $columns->[$k][$i];
3432             }
3433 3         12 $t->add_row(@row);
3434             }
3435            
3436 1         105 return "$t";
3437             }
3438              
3439             sub sweep {
3440 9     9 0 12 my $r = shift;
3441            
3442 9         33 my ($x1, $x_margin, $x2, $x_func)
3443             = Rstats::Func::args_array($r, ['x1', 'margin', 'x2', 'FUN'], @_);
3444            
3445 9         53 my $x_margin_values = $x_margin->values;
3446 9 100       51 my $func = defined $x_func ? $x_func->value : '-';
3447            
3448 9         76 my $x2_dim_values = Rstats::Func::dim($r, $x2)->values;
3449 9         116 my $x1_dim_values = Rstats::Func::dim($r, $x1)->values;
3450            
3451 9         65 my $x1_length = Rstats::Func::get_length($r, $x1);
3452            
3453 9         15 my $x_result_elements = [];
3454 9         27 for (my $x1_pos = 0; $x1_pos < $x1_length; $x1_pos++) {
3455 54         204 my $x1_index = Rstats::Util::pos_to_index($x1_pos, $x1_dim_values);
3456            
3457 54         81 my $new_index = [];
3458 54         100 for my $x_margin_value (@$x_margin_values) {
3459 60         129 push @$new_index, $x1_index->[$x_margin_value - 1];
3460             }
3461            
3462 54         65 my $e1 = $x2->value(@{$new_index});
  54         270  
3463 54         223 push @$x_result_elements, $e1;
3464             }
3465 9         601 my $x3 = Rstats::Func::c_($r, @$x_result_elements);
3466            
3467 9         117 my $x4;
3468 9 100       40 if ($func eq '+') {
    100          
    100          
    100          
    100          
    50          
3469 1         4 $x4 = $x1 + $x3;
3470             }
3471             elsif ($func eq '-') {
3472 4         14 $x4 = $x1 - $x3;
3473             }
3474             elsif ($func eq '*') {
3475 1         5 $x4 = $x1 * $x3;
3476             }
3477             elsif ($func eq '/') {
3478 1         4 $x4 = $x1 / $x3;
3479             }
3480             elsif ($func eq '**') {
3481 1         5 $x4 = $x1 ** $x3;
3482             }
3483             elsif ($func eq '%') {
3484 1         4 $x4 = $x1 % $x3;
3485             }
3486            
3487 9         50 Rstats::Func::copy_attrs_to($r, $x1, $x4);
3488            
3489 9         94 return $x4;
3490             }
3491              
3492             sub set_seed {
3493 2     2 0 3 my ($r, $seed) = @_;
3494            
3495 2         8 $r->{seed} = $seed;
3496             }
3497              
3498             sub runif {
3499 6     6 0 10 my $r = shift;
3500              
3501 6         25 my ($x_count, $x_min, $x_max)
3502             = Rstats::Func::args_array($r, ['count', 'min', 'max'], @_);
3503            
3504 6         43 my $count = $x_count->value;
3505 6 100       24 my $min = defined $x_min ? $x_min->value : 0;
3506 6 100       18 my $max = defined $x_max ? $x_max->value : 1;
3507 6 50       15 Carp::croak "runif third argument must be bigger than second argument"
3508             if $min > $max;
3509            
3510 6         10 my $diff = $max - $min;
3511 6         8 my @x1_elements;
3512 6 100       15 if (defined $r->{seed}) {
3513 2         5 srand $r->{seed};
3514             }
3515            
3516 6         14 for (1 .. $count) {
3517 220         265 my $rand = rand($diff) + $min;
3518 220         296 push @x1_elements, $rand;
3519             }
3520            
3521 6         10 $r->{seed} = undef;
3522            
3523 6         2165 return Rstats::Func::c_($r, @x1_elements);
3524             }
3525              
3526             sub apply {
3527 10     10 0 17 my $r = shift;
3528            
3529 10         24 my $func_name = splice(@_, 2, 1);
3530 10 100       251 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3531              
3532 10         91 my ($x1, $x_margin)
3533             = Rstats::Func::args_array($r, ['x1', 'margin'], @_);
3534              
3535 10         130 my $dim_values = Rstats::Func::dim($r, $x1)->values;
3536 10         79 my $margin_values = $x_margin->values;
3537 10         21 my $new_dim_values = [];
3538 10         21 for my $i (@$margin_values) {
3539 14         38 push @$new_dim_values, $dim_values->[$i - 1];
3540             }
3541            
3542 10         43 my $x1_length = Rstats::Func::get_length($r, $x1);
3543 10         17 my $new_elements_array = [];
3544 10         29 for (my $i = 0; $i < $x1_length; $i++) {
3545 186         818 my $index = Rstats::Util::pos_to_index($i, $dim_values);
3546 186         1002 my $e1 = $x1->value(@$index);
3547 186         354 my $new_index = [];
3548 186         377 for my $i (@$margin_values) {
3549 264         661 push @$new_index, $index->[$i - 1];
3550             }
3551 186         486 my $new_pos = Rstats::Util::index_to_pos($new_index, $new_dim_values);
3552 186   100     549 $new_elements_array->[$new_pos] ||= [];
3553 186         234 push @{$new_elements_array->[$new_pos]}, $e1;
  186         756  
3554             }
3555            
3556 10         19 my $new_elements = [];
3557 10         21 for my $element_array (@$new_elements_array) {
3558 48         2870 push @$new_elements, $func->($r, Rstats::Func::c_($r, @$element_array));
3559             }
3560              
3561 10         304 my $x2 = Rstats::Func::c_($r, @$new_elements);
3562 10         124 Rstats::Func::copy_attrs_to($r, $x1, $x2);
3563 10         129 $x2->{dim} = Rstats::Func::c_integer($r, @$new_dim_values);
3564            
3565 10 100       118 if ($x2->{dim}->get_length == 1) {
3566 6         33 delete $x2->{dim};
3567             }
3568            
3569 10         176 return $x2;
3570              
3571             }
3572            
3573             sub mapply {
3574 3     3 0 5 my $r = shift;
3575            
3576 3         8 my $func_name = splice(@_, 0, 1);
3577 3 50       71 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3578              
3579 3         20 my @xs = @_;
3580 3         7 @xs = map { Rstats::Func::c_($r, $_) } @xs;
  6         87  
3581            
3582             # Fix length
3583 3         6 my @xs_length = map { Rstats::Func::get_length($r, $_) } @xs;
  6         26  
3584 3         9 my $max_length = List::Util::max @xs_length;
3585 3         11 for my $x (@xs) {
3586 6 100       32 if (Rstats::Func::get_length($r, $x) < $max_length) {
3587 1         104 $x = Rstats::Func::array($r, $x, $max_length);
3588             }
3589             }
3590            
3591             # Apply
3592 3         6 my $new_xs = [];
3593 3         9 for (my $i = 0; $i < $max_length; $i++) {
3594 10         17 my @args = map { $_->value($i + 1) } @xs;
  20         105  
3595 10         24 my $x = $func->($r, @args);
3596 10         39 push @$new_xs, $x;
3597             }
3598            
3599 3 100       9 if (@$new_xs == 1) {
3600 1         9 return $new_xs->[0];
3601             }
3602             else {
3603 2         6 return Rstats::Func::list($r, @$new_xs);
3604             }
3605             }
3606            
3607             sub tapply {
3608 1     1 0 2 my $r = shift;
3609            
3610 1         3 my $func_name = splice(@_, 2, 1);
3611 1 50       23 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3612              
3613 1         10 my ($x1, $x2)
3614             = Rstats::Func::args_array($r, ['x1', 'x2'], @_);
3615            
3616 1         3 my $new_values = [];
3617 1         7 my $x1_values = $x1->values;
3618 1         6 my $x2_values = $x2->values;
3619            
3620             # Group values
3621 1         14 for (my $i = 0; $i < Rstats::Func::get_length($r, $x1); $i++) {
3622 5         8 my $x1_value = $x1_values->[$i];
3623 5         7 my $index = $x2_values->[$i];
3624 5   100     15 $new_values->[$index] ||= [];
3625 5         6 push @{$new_values->[$index]}, $x1_value;
  5         28  
3626             }
3627            
3628             # Apply
3629 1         2 my $new_values2 = [];
3630 1         5 for (my $i = 1; $i < @$new_values; $i++) {
3631 2         3 my $x = $func->($r, Rstats::Func::c_($r, @{$new_values->[$i]}));
  2         72  
3632 2         20 push @$new_values2, $x;
3633             }
3634            
3635 1         6 my $x4_length = @$new_values2;
3636 1         62 my $x4 = Rstats::Func::array($r, Rstats::Func::c_($r, @$new_values2), $x4_length);
3637 1         36 Rstats::Func::names($r, $x4, Rstats::Func::levels($r, $x2));
3638            
3639 1         14 return $x4;
3640             }
3641              
3642             sub lapply {
3643 2     2 0 3 my $r = shift;
3644            
3645 2         17 my $func_name = splice(@_, 1, 1);
3646 2 50       45 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3647              
3648 2         19 my ($x1) = Rstats::Func::args_array($r, ['x1'], @_);
3649            
3650 2         5 my $new_elements = [];
3651 2         3 for my $element (@{$x1->list}) {
  2         43  
3652 4         59 push @$new_elements, $func->($r, $element);
3653             }
3654            
3655 2         6 my $x2 = Rstats::Func::list($r, @$new_elements);
3656 2         19 Rstats::Func::copy_attrs_to($r, $x1, $x2);
3657            
3658 2         8 return $x2;
3659             }
3660            
3661             sub sapply {
3662 1     1 0 2 my $r = shift;
3663 1         8 my $x1 = $r->lapply(@_);
3664            
3665 1         2 my $x2 = Rstats::Func::c_($r, @{$x1->list});
  1         22  
3666            
3667 1         28 return $x2;
3668             }
3669              
3670             sub to_string {
3671 565     565 0 865 my ($r, $x1) = @_;
3672            
3673 565 100 66     2339 if ($x1->{object_type} eq 'NULL') {
    100          
    100          
    50          
3674 1         7 return "NULL";
3675             }
3676             elsif ($x1->{object_type} eq 'array' || $x1->{object_type} eq 'factor') {
3677 560         1248 return Rstats::Func::to_string_array(@_);
3678             }
3679             elsif ($x1->{object_type} eq 'list') {
3680 3         10 return Rstats::Func::to_string_list(@_);
3681             }
3682             elsif ($x1->{object_type} eq 'data.frame') {
3683 1         6 return Rstats::Func::to_string_dataframe(@_);
3684             }
3685             else {
3686 0         0 my $class = ref $x1;
3687 0         0 croak "Error in to_string() : $class not implemented(Rstats::Func::to_string)";
3688             }
3689             }
3690              
3691             sub get {
3692 1017     1017 0 1703 my ($r, $x1) = @_;
3693            
3694 1017 100 66     3452 if ($x1->{object_type} eq 'array' || $x1->{object_type} eq 'factor') {
    100          
    50          
3695 998         2288 return Rstats::Func::get_array(@_);
3696             }
3697             elsif ($x1->{object_type} eq 'list') {
3698 3         19 return Rstats::Func::get_list(@_);
3699             }
3700             elsif ($x1->{object_type} eq 'data.frame') {
3701 16         52 return Rstats::Func::get_dataframe(@_);
3702             }
3703             else {
3704 0         0 croak "Error in get() : Not implemented";
3705             }
3706             }
3707              
3708             sub getin {
3709 240     240 0 389 my ($r, $x1) = @_;
3710            
3711 240 50       895 if ($x1->{object_type} eq 'array') {
    100          
    50          
3712 0         0 return Rstats::Func::getin_array(@_);
3713             }
3714             elsif ($x1->{object_type} eq 'list') {
3715 141         298 return Rstats::Func::getin_list(@_);
3716             }
3717             elsif ($x1->{object_type} eq 'data.frame') {
3718 99         241 return Rstats::Func::getin_dataframe(@_);
3719             }
3720             else {
3721 0         0 croak "Error in getin() : Not implemented";
3722             }
3723             }
3724              
3725             sub _levels_h {
3726 1     1   2 my $r = shift;
3727            
3728 1         2 my $x1 = shift;
3729            
3730 1         2 my $levels_h = {};
3731 1         23 my $levels = Rstats::Func::levels($r, $x1)->values;
3732 1         9 for (my $i = 1; $i <= @$levels; $i++) {
3733 3         33 $levels_h->{$levels->[$i - 1]} = Rstats::Func::c_integer($r, $i);
3734             }
3735            
3736 1         3 return $levels_h;
3737             }
3738              
3739             sub set_array {
3740 50     50 0 67 my $r = shift;
3741            
3742 50         61 my $x1 = shift;
3743 50         561 my $x2 = Rstats::Func::to_object($r, shift);
3744            
3745 50         284 my $at = $x1->at;
3746 50 50       130 my $_indexs = ref $at eq 'ARRAY' ? $at : [$at];
3747 50         139 my ($poss, $x2_dim) = @{Rstats::Util::parse_index($r, $x1, 0, $_indexs)};
  50         185  
3748            
3749 50         369 my $type;
3750             my $x1_elements;
3751 50 100       1551 if (Rstats::Func::is_factor($r, $x1)) {
3752 1         31 $x1_elements = Rstats::Func::decompose($r, $x1);
3753 1 50       11 $x2 = Rstats::Func::as_character($r, $x2) unless Rstats::Func::is_character($r, $x2);
3754 1         17 my $x2_elements = Rstats::Func::decompose($r, $x2);
3755 1         4 my $levels_h = Rstats::Func::_levels_h($r, $x1);
3756 1         5 for (my $i = 0; $i < @$poss; $i++) {
3757 2         5 my $pos = $poss->[$i];
3758 2         5 my $element = $x2_elements->[(($i + 1) % @$poss) - 1];
3759 2 50       41 if (Rstats::Func::is_na($r, $element)) {
3760 0         0 $x1_elements->[$pos] = Rstats::Func::c_logical($r, undef);
3761             }
3762             else {
3763 2         6 my $value = Rstats::Func::value($r, $element);
3764 2 50       7 if ($levels_h->{$value}) {
3765 2         23 $x1_elements->[$pos] = $levels_h->{$value};
3766             }
3767             else {
3768 0         0 Carp::carp "invalid factor level, NA generated";
3769 0         0 $x1_elements->[$pos] = Rstats::Func::c_logical($r, undef);
3770             }
3771             }
3772             }
3773 1         7 $type = $x1->get_type;
3774             }
3775             else {
3776             # Upgrade mode if type is different
3777 49 100       250 if ($x1->get_type ne $x2->get_type) {
3778 1         2 my $x1_tmp;
3779 1         2 ($x1_tmp, $x2) = @{Rstats::Func::upgrade_type($r, [$x1, $x2])};
  1         49  
3780 1         14 Rstats::Func::copy_attrs_to($r, $x1_tmp, $x1);
3781 1         25 $x1->vector($x1_tmp->vector);
3782            
3783 1         14 $type = $x1_tmp->get_type;
3784             }
3785             else {
3786 48         335 $type = $x1->get_type;
3787             }
3788              
3789 49         1725 $x1_elements = Rstats::Func::decompose($r, $x1);
3790              
3791 49         484 my $x2_elements = Rstats::Func::decompose($r, $x2);
3792 49         150 for (my $i = 0; $i < @$poss; $i++) {
3793 53         91 my $pos = $poss->[$i];
3794 53         401 $x1_elements->[$pos] = $x2_elements->[(($i + 1) % @$poss) - 1];
3795             }
3796             }
3797            
3798 50         620 $DB::single = 1;
3799 50         736 my $x1_tmp = Rstats::Func::compose($r, $type, $x1_elements);
3800 50         1248 $x1->vector($x1_tmp->vector);
3801 50         580 $x1->{type} = $x1_tmp->{type};
3802 50         85 $x1->{object_type} = $x1_tmp->{object_type};
3803            
3804 50         1144 return $x1;
3805             }
3806              
3807             sub sort {
3808 86     86 0 152 my $r = shift;
3809            
3810 86         346 my ($x1, $x_decreasing) = Rstats::Func::args_array($r, ['x1', 'decreasing', 'na.last'], @_);
3811            
3812 86 100       270 my $decreasing = defined $x_decreasing ? $x_decreasing->value : 0;
3813            
3814 86   100     124 my @x2_elements = grep { !Rstats::Func::is_na($r, $_) && !Rstats::Func::is_nan($r, $_) } @{Rstats::Func::decompose($r, $x1)};
  415         5068  
  86         1649  
3815            
3816             my $x3_elements = $decreasing
3817 3 50       17 ? [reverse sort { ($a > $b) ? 1 : ($a == $b) ? 0 : -1 } @x2_elements]
    100          
3818 86 50       593 : [sort { ($a > $b) ? 1 : ($a == $b) ? 0 : -1 } @x2_elements];
  362 100       2537  
    100          
3819              
3820 86         2915 return Rstats::Func::c_($r, @$x3_elements);
3821             }
3822              
3823             sub value {
3824 35725     35725 0 46085 my $r = shift;
3825 35725         43456 my $x1 = shift;
3826            
3827 35725         38456 my $e1;
3828 35725         164387 my $dim_values = Rstats::Func::values($r, $x1->dim_as_array);
3829 35725         533847 my $x1_elements = Rstats::Func::decompose($r, $x1);
3830 35725 100       83911 if (@_) {
3831 1838 100       4878 if (@$dim_values == 1) {
    100          
3832 118         218 $e1 = $x1_elements->[$_[0] - 1];
3833             }
3834             elsif (@$dim_values == 2) {
3835 807         2395 $e1 = $x1_elements->[($_[0] + $dim_values->[0] * ($_[1] - 1)) - 1];
3836             }
3837             else {
3838 913         4783 $e1 = Rstats::Func::decompose($r, $x1->get(@_))->[0];
3839             }
3840            
3841             }
3842             else {
3843 33887         54482 $e1 = $x1_elements->[0];
3844             }
3845            
3846 35725 50       390375 return defined $e1 ? Rstats::Func::first_value($r, $e1) : undef;
3847             }
3848              
3849             1;
3850              
3851             =head1 NAME
3852              
3853             Rstats::Func - Functions
3854