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         39  
  21         584  
4 21     21   104 use warnings;
  21         39  
  21         704  
5              
6             require Rstats;
7              
8 21     21   105 use Carp 'croak';
  21         49  
  21         993  
9 21     21   128 use Rstats::Func;
  21         53  
  21         584  
10 21     21   109 use Rstats::Util;
  21         31  
  21         517  
11 21     21   17303 use Text::UnicodeTable::Simple;
  21         860470  
  21         911  
12              
13 21     21   202 use List::Util ();
  21         39  
  21         329  
14 21     21   17688 use POSIX ();
  21         137303  
  21         608  
15 21     21   15456 use Math::Round ();
  21         22898  
  21         396  
16 21     21   18200 use Encode ();
  21         240875  
  21         523162  
17              
18             sub factor {
19 86     86 0 150 my $r = shift;
20            
21 86         455 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       1088 $x1 = Rstats::Func::as_character($r, $x1) unless Rstats::Func::is_character($r, $x1);
26            
27             # default - levels
28 86 100       501 unless (defined $x_levels) {
29 72         198 $x_levels = Rstats::Func::sort($r, unique($r, $x1), {'na.last' => Rstats::Func::TRUE($r)});
30             }
31            
32             # default - exclude
33 86 100       2144 $x_exclude = NA($r) unless defined $x_exclude;
34            
35             # fix levels
36 86 100 66     488 if (defined $x_exclude->value && Rstats::Func::length($r, $x_exclude)->value) {
37 1         3 my $new_a_levels_values = [];
38 1         2 for my $x_levels_value (@{$x_levels->values}) {
  1         7  
39 3         4 my $match;
40 3         5 for my $x_exclude_value (@{$x_exclude->values}) {
  3         16  
41 3 100 33     33 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       12 push @$new_a_levels_values, $x_levels_value unless $match;
50             }
51 1         27 $x_levels = Rstats::Func::c_($r, @$new_a_levels_values);
52             }
53            
54             # default - labels
55 86 100       249 unless (defined $x_labels) {
56 79         140 $x_labels = $x_levels;
57             }
58            
59             # default - ordered
60 86 100       1529 $x_ordered = Rstats::Func::is_ordered($r, $x1) unless defined $x_ordered;
61            
62 86         855 my $x1_values = $x1->values;
63            
64 86         1116 my $labels_length = Rstats::Func::length($r, $x_labels)->value;
65 86         1208 my $levels_length = Rstats::Func::length($r, $x_levels)->value;
66 86 100 100     650 if ($labels_length == 1 && Rstats::Func::get_length($r, $x1) != 1) {
    50          
67 1         7 my $value = $x_labels->value;
68 1         8 $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         129 my $levels;
76 86         467 my $x_levels_values = $x_levels->values;
77 86         320 for (my $i = 1; $i <= $levels_length; $i++) {
78 217         390 my $x_levels_value = $x_levels_values->[$i - 1];
79 217         748 $levels->{$x_levels_value} = $i;
80             }
81            
82 86         169 my $f1_values = [];
83 86         190 for my $x1_value (@$x1_values) {
84 347 100       607 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       803 ? $levels->{$x1_value}
90             : undef;
91 346         690 push @$f1_values, $f1_value;
92             }
93             }
94            
95 86         1027 my $f1 = Rstats::Func::c_integer($r, @$f1_values);
96 86 100       328 if ($x_ordered) {
97 7         85 $f1->{class} = Rstats::Func::c_character($r, 'factor', 'ordered');
98             }
99             else {
100 79         937 $f1->{class} = Rstats::Func::c_character($r, 'factor');
101             }
102 86         891 $f1->{levels} = Rstats::Func::as_vector($r, $x_labels);
103            
104 86         180 $f1->{type} = 'integer';
105 86         148 $f1->{object_type} = 'array';
106            
107 86         1073 return $f1;
108             }
109              
110             sub ordered {
111 4     4 0 11 my $r = shift;
112            
113 4 100       18 my $opt = ref $_[-1] eq 'HASH' ? pop : {};
114 4         34 $opt->{ordered} = Rstats::Func::TRUE($r);
115            
116 4         14 factor($r, @_, $opt);
117             }
118              
119             sub list {
120 90     90 0 167 my $r = shift;
121            
122 90         232 my @elements = @_;
123            
124 90 100       186 @elements = map { !Rstats::Func::is_list($r, $_) ? Rstats::Func::to_object($r, $_) : $_ } @elements;
  181         1780  
125            
126 90         493 my $list = Rstats::Func::new_list($r);
127 90         2209 $list->list(\@elements);
128 90         2441 $list->r($r);
129            
130 90         676 return $list;
131             }
132              
133             sub data_frame {
134 45     45 0 103 my $r = shift;
135            
136 45         153 my @data = @_;
137            
138 45 100 66     185 return cbind($r, @data) if ref $data[0] && Rstats::Func::is_data_frame($r, $data[0]);
139            
140 44         95 my $elements = [];
141            
142             # name count
143 44         141 my $name_count = {};
144            
145             # count
146 44         86 my $counts = [];
147 44         84 my $column_names = [];
148 44         80 my $row_names = [];
149 44         74 my $row_count = 1;
150 44         194 while (my ($name, $v) = splice(@data, 0, 2)) {
151 113 100 100     1210 if (Rstats::Func::is_character($r, $v) && !grep {$_ eq 'AsIs'} @{$v->class->values}) {
  34         214  
  34         231  
152 31         89 $v = Rstats::Func::as_factor($r, $v);
153             }
154              
155 113         1768 my $dim_values = Rstats::Func::dim($r, $v)->values;
156 113 50       483 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         521 my $count = Rstats::Func::get_length($r, $v);
176 113         239 push @$counts, $count;
177 113         142 my $fix_name;
178 113 100       317 if (my $count = $name_count->{$name}) {
179 2         9 $fix_name = "$name.$count";
180             }
181             else {
182 111         200 $fix_name = $name;
183             }
184 113         201 push @$column_names, $fix_name;
185 113         242 push @$elements, $v;
186             }
187 113         260 push @$row_names, "$row_count";
188 113         183 $row_count++;
189 113         838 $name_count->{$name}++;
190             }
191            
192             # Max count
193 44         147 my $max_count = List::Util::max @$counts;
194            
195             # Check multiple number
196 44         95 for my $count (@$counts) {
197 113 50       354 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         171 for (my $i = 0; $i < @$counts; $i++) {
204 113         182 my $count = $counts->[$i];
205            
206 113         252 my $repeat = $max_count / $count;
207 113 100       429 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         277 my $data_frame = Rstats::Func::new_data_frame($r);
216 44         119 $data_frame->{row_length} = $max_count;
217 44         1105 $data_frame->list($elements);
218 44         2801 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         2054 $data_frame->r($r);
228            
229 44         451 return $data_frame;
230             }
231              
232             sub matrix {
233 75     75 0 132 my $r = shift;
234            
235            
236 75         328 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       272 Carp::croak "matrix method need data as frist argument"
240             unless defined $x1;
241            
242             # Row count
243 75         101 my $nrow;
244 75 100       491 $nrow = $x_nrow->value if defined $x_nrow;
245            
246             # Column count
247 75         131 my $ncol;
248 75 100       438 $ncol = $x_ncol->value if defined $x_ncol;
249            
250             # By row
251 75         118 my $byrow;
252 75 100       199 $byrow = $x_byrow->value if defined $x_byrow;
253            
254 75         383 my $x1_values = $x1->values;
255 75         381 my $x1_length = Rstats::Func::get_length($r, $x1);
256 75 100 100     425 if (!defined $nrow && !defined $ncol) {
    100          
    100          
257 9         15 $nrow = $x1_length;
258 9         17 $ncol = 1;
259             }
260             elsif (!defined $nrow) {
261 1         3 $nrow = int($x1_length / $ncol);
262 1   50     5 $nrow ||= 1;
263             }
264             elsif (!defined $ncol) {
265 3         10 $ncol = int($x1_length / $nrow);
266 3   100     16 $ncol ||= 1;
267             }
268 75         147 my $length = $nrow * $ncol;
269            
270 75         164 my $dim = [$nrow, $ncol];
271 75         111 my $matrix;
272             my $x_matrix;
273              
274 75 50       656 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         1471 $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         41 $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       179 if ($byrow) {
294 1         133 $matrix = Rstats::Func::array(
295             $r,
296             $x_matrix,
297             Rstats::Func::c_($r, $dim->[1], $dim->[0]),
298             );
299            
300 1         32 $matrix = Rstats::Func::t($r, $matrix);
301             }
302             else {
303 74         9062 $matrix = Rstats::Func::array($r, $x_matrix, Rstats::Func::c_($r, @$dim));
304             }
305            
306 75         2604 return $matrix;
307             }
308              
309              
310              
311              
312             sub dimnames {
313 61     61 0 160 my $r = shift;
314            
315 61         111 my $x1 = shift;
316            
317 61 100       172 if (@_) {
318 46         69 my $dimnames_list = shift;
319 46 50       175 if ($dimnames_list->{object_type} eq 'list') {
320 46         235 my $length = Rstats::Func::get_length($r, $dimnames_list);
321 46         95 my $dimnames = [];
322 46         167 for (my $i = 0; $i < $length; $i++) {
323 92         570 my $x_dimname = $dimnames_list->getin($i + 1);
324 92 50       948 if (is_character($r, $x_dimname)) {
325 92         886 my $dimname = Rstats::Func::as_vector($r, $x_dimname);
326 92         702 push @$dimnames, $dimname;
327             }
328             else {
329 0         0 croak "dimnames must be character list";
330             }
331             }
332 46         130 $x1->{dimnames} = $dimnames;
333            
334 46 100       449 if (Rstats::Func::is_data_frame($r, $x1)) {
335 44         519 $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       54 if (exists $x1->{dimnames}) {
344 5         14 my $x_dimnames = Rstats::Func::list($r);
345 5         127 $x_dimnames->list($x1->{dimnames});
346             }
347             else {
348 10         66 return Rstats::Func::NULL($r);
349             }
350             }
351             }
352              
353             sub rownames {
354 19     19 0 33 my $r = shift;
355            
356 19         33 my $x1 = shift;
357            
358 19 100       51 if (@_) {
359 3         12 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         35 $x1->{dimnames}[0] = Rstats::Func::as_vector($r, $x_rownames);
366             }
367             else {
368 16         88 my $x_rownames = Rstats::Func::NULL($r);
369 16 100       60 if (defined $x1->{dimnames}[0]) {
370 10         107 $x_rownames = Rstats::Func::as_vector($r, $x1->{dimnames}[0]);
371             }
372 16         132 return $x_rownames;
373             }
374             }
375              
376              
377             sub colnames {
378 18     18 0 38 my $r = shift;
379            
380 18         40 my $x1 = shift;
381            
382 18 100       51 if (@_) {
383 3         12 my $x_colnames = Rstats::Func::to_object($r, shift);
384            
385 3 100       13 unless (exists $x1->{dimnames}) {
386 2         5 $x1->{dimnames} = [];
387             }
388            
389 3         35 $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       63 if (defined $x1->{dimnames}[1]) {
394 9         92 $x_colnames = Rstats::Func::as_vector($r, $x1->{dimnames}[1]);
395             }
396 15         198 return $x_colnames;
397             }
398             }
399              
400             sub labels {
401 1     1 0 3 my $r = shift;
402 1         9 return $r->as->character(@_);
403             }
404              
405             sub as_list {
406 2     2 0 3 my $r = shift;
407            
408 2         4 my $x1 = shift;
409            
410 2 100       7 if (exists $x1->{list}) {
411 1         4 return $x1;
412             }
413             else {
414 1         6 my $list = Rstats::Func::new_list($r);;
415 1         11 my $x2 = Rstats::Func::as_vector($r, $x1);
416 1         31 $list->list([$x2]);
417            
418 1         7 return $list;
419             }
420             }
421              
422             sub as_factor {
423 43     43 0 67 my $r = shift;
424            
425 43         67 my $x1 = shift;
426            
427 43 100       858 if (Rstats::Func::is_factor($r, $x1)) {
428 11         93 return $x1;
429             }
430             else {
431 32 50       312 my $a = is_character($r, $x1) ? $x1 : Rstats::Func::as_character($r, $x1);
432 32         219 my $f = Rstats::Func::factor($r, $a);
433            
434 32         112 return $f;
435             }
436             }
437              
438             sub as_matrix {
439 14     14 0 35 my $r = shift;
440            
441 14         25 my $x1 = shift;
442            
443 14         70 my $x1_dim_elements = $x1->dim_as_array->values;
444 14         75 my $x1_dim_count = @$x1_dim_elements;
445 14         28 my $x2_dim_elements = [];
446 14         18 my $row;
447             my $col;
448 14 100       40 if ($x1_dim_count == 2) {
449 4         8 $row = $x1_dim_elements->[0];
450 4         7 $col = $x1_dim_elements->[1];
451             }
452             else {
453 10         14 $row = 1;
454 10         42 $row *= $_ for @$x1_dim_elements;
455 10         15 $col = 1;
456             }
457            
458 14         130 my $x2 = Rstats::Func::as_vector($r, $x1);
459            
460 14         48 return Rstats::Func::matrix($r, $x2, $row, $col);
461             }
462              
463             sub I {
464 3     3 0 8 my $r = shift;
465            
466 3         4 my $x1 = shift;
467            
468 3         45 my $x2 = Rstats::Func::c_($r, $x1);
469 3         24 Rstats::Func::copy_attrs_to($r, $x1, $x2);
470 3         20 $x2->class('AsIs');
471            
472 3         18 return $x2;
473             }
474              
475             sub subset {
476 2     2 0 5 my $r = shift;
477            
478 2         12 my ($x1, $x_condition, $x_names)
479             = args_array($r, ['x1', 'condition', 'names'], @_);
480            
481 2 100       14 $x_names = Rstats::Func::NULL($r) unless defined $x_names;
482            
483 2         14 my $x2 = $x1->get($x_condition, $x_names);
484            
485 2         9 return $x2;
486             }
487              
488             sub t {
489 5     5 0 9 my $r = shift;
490            
491 5         10 my $x1 = shift;
492            
493 5         64 my $x1_row = Rstats::Func::dim($r, $x1)->values->[0];
494 5         77 my $x1_col = Rstats::Func::dim($r, $x1)->values->[1];
495            
496 5         34 my $x2 = matrix($r, 0, $x1_col, $x1_row);
497            
498 5         16 for my $row (1 .. $x1_row) {
499 17         36 for my $col (1 .. $x1_col) {
500 36         196 my $value = $x1->value($row, $col);
501 36         196 $x2->at($col, $row);
502 36         78 Rstats::Func::set($r, $x2, $value);
503             }
504             }
505            
506 5         26 return $x2;
507             }
508              
509             sub transform {
510 2     2 0 4 my $r = shift;
511            
512 2         4 my $x1 = shift;
513 2         5 my @args = @_;
514              
515 2         27 my $new_names = Rstats::Func::names($r, $x1)->values;
516 2         52 my $new_elements = $x1->list;
517            
518 2         35 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       28 if (Rstats::Func::is_character($r, $new_v)) {
522 2         9 $new_v = Rstats::Func::I($r, $new_v);
523             }
524              
525 3         15 my $found_pos = -1;
526 3         10 for (my $i = 0; $i < @$names; $i++) {
527 5         10 my $name = $names->[$i];
528 5 100       17 if ($new_name eq $name) {
529 2         3 $found_pos = $i;
530 2         5 last;
531             }
532             }
533            
534 3 100       74 if ($found_pos == -1) {
535 1         2 push @$new_names, $new_name;
536 1         6 push @$new_elements, $new_v;
537             }
538             else {
539 2         25 $new_elements->[$found_pos] = $new_v;
540             }
541             }
542            
543            
544 2         3 my @new_args;
545 2         7 for (my $i = 0; $i < @$new_names; $i++) {
546 7         24 push @new_args, $new_names->[$i], $new_elements->[$i];
547             }
548            
549 2         6 my $x2 = Rstats::Func::data_frame($r, @new_args);
550            
551 2         11 return $x2;
552             }
553              
554             sub na_omit {
555 1     1 0 3 my $r = shift;
556            
557 1         3 my $x1 = shift;
558            
559 1         3 my @poss;
560 1         3 for my $v (@{$x1->list}) {
  1         30  
561 3         21 for (my $index = 1; $index <= $x1->{row_length}; $index++) {
562 9 100       59 push @poss, $index unless defined $v->value($index);
563             }
564             }
565            
566 1         37 my $x2 = $x1->get(-c_($r, @poss), NULL($r));
567            
568 1         20 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 58 my $r = shift;
620            
621 37         49 my ($type1, $type2) = @_;
622            
623 37 100       89 if ($type_level->{$type1} > $type_level->{$type2}) {
624 4         13 return $type1;
625             }
626             else {
627 33         165 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 7 my $r = shift;
644            
645 4         25 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         32 my $file = $x_file->value;
649 4 50       257 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       12 my $encoding = defined $x_encoding ? $x_encoding->value : 'UTF-8';
655 4 100       20 my $skip = defined $x_skip ? $x_skip->value : 0;
656 4 100       16 my $header_opt = defined $x_header ? $x_header->value : 0;
657            
658 4         6 my $type_columns;
659 4         6 my $columns = [];
660 4         7 my $row_size;
661             my $header;
662 4         89 while (my $line = <$fh>) {
663 14 100       31 if ($skip > 0) {
664 2         3 $skip--;
665 2         7 next;
666             }
667 12         37 $line = Encode::decode($encoding, $line);
668 12         688 $line =~ s/\x0D?\x0A?$//;
669            
670 12 100 100     44 if ($header_opt && !$header) {
671 1         14 $header = [split(/$sep/, $line)];
672 1         5 next;
673             }
674            
675 11         77 my @row = split(/$sep/, $line);
676 11         15 my $current_row_size = @row;
677 11   66     33 $row_size ||= $current_row_size;
678            
679             # Row size different
680 11 50       24 Carp::croak "line $. did not have $row_size elements"
681             if $current_row_size != $row_size;
682            
683 11   100     39 $type_columns ||= [('logical') x $row_size];
684            
685 11         30 for (my $i = 0; $i < @row; $i++) {
686            
687 37   100     95 $columns->[$i] ||= [];
688 37         43 push @{$columns->[$i]}, $row[$i];
  37         83  
689 37         43 my $type;
690 37 100       433 if (defined Rstats::Util::looks_like_na($row[$i])) {
    100          
    100          
    100          
    100          
691 5         8 $type = 'logical';
692             }
693             elsif (defined Rstats::Util::looks_like_logical($row[$i])) {
694 4         8 $type = 'logical';
695             }
696             elsif (defined Rstats::Util::looks_like_integer($row[$i])) {
697 10         16 $type = 'integer';
698             }
699             elsif (defined Rstats::Util::looks_like_double($row[$i])) {
700 10         14 $type = 'double';
701             }
702             elsif (defined Rstats::Util::looks_like_complex($row[$i])) {
703 4         6 $type = 'complex';
704             }
705             else {
706 4         7 $type = 'character';
707             }
708 37         90 $type_columns->[$i] = Rstats::Func::higher_type($r, $type_columns->[$i], $type);
709             }
710             }
711            
712 4         7 my $data_frame_args = [];
713 4         13 for (my $i = 0; $i < $row_size; $i++) {
714 11 100       25 if (defined $header->[$i]) {
715 2         6 push @$data_frame_args, $header->[$i];
716             }
717             else {
718 9         27 push @$data_frame_args, "V" . ($i + 1);
719             }
720 11         16 my $type = $type_columns->[$i];
721 11 100       46 if ($type eq 'character') {
    100          
    100          
    100          
722 1         2 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  1         56  
723 1         17 push @$data_frame_args, Rstats::Func::as_factor($r, $x1);
724             }
725             elsif ($type eq 'complex') {
726 1         3 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  1         42  
727 1         170 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         108  
731 4         183 push @$data_frame_args, Rstats::Func::as_double($r, Rstats::Func::as_double($r, $x1));
732             }
733             elsif ($type eq 'integer') {
734 4         6 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  4         125  
735 4         205 push @$data_frame_args, Rstats::Func::as_integer($r, $x1);
736             }
737             else {
738 1         3 my $x1 = Rstats::Func::c_($r, @{$columns->[$i]});
  1         42  
739 1         54 push @$data_frame_args, Rstats::Func::as_logical($r, $x1);
740             }
741             }
742            
743 4         12 my $d1 = Rstats::Func::data_frame($r, @$data_frame_args);
744            
745 4         170 return $d1;
746             }
747              
748             sub interaction {
749 5     5 0 10 my $r = shift;
750            
751 5         7 my $opt;
752 5 100       21 $opt = ref $_[-1] eq 'HASH' ? pop : {};
753 5         11 my @xs = map { Rstats::Func::as_factor($r, to_object($r, $_)) } @_;
  11         45  
754 5         9 my ($x_drop, $x_sep);
755 5         18 ($x_drop, $x_sep) = args_array($r, ['drop', 'sep'], $opt);
756            
757 5 100       88 $x_sep = Rstats::Func::c_($r, ".") unless defined $x_sep;
758 5         41 my $sep = $x_sep->value;
759            
760 5 100       37 $x_drop = Rstats::Func::FALSE($r) unless defined $x_drop;
761            
762 5         6 my $max_length;
763 5         10 my $values_list = [];
764 5         10 for my $x (@xs) {
765 11         120 my $length = Rstats::Func::length($r, $x)->value;
766 11 100 66     80 $max_length = $length if !defined $max_length || $length > $max_length;
767             }
768            
769             # Vector
770 5         11 my $f1_elements = [];
771 5         16 for (my $i = 0; $i < $max_length; $i++) {
772 18         30 my $chars = [];
773 18         32 for my $x (@xs) {
774 39         2024 my $fix_x = Rstats::Func::as_character($r, $x);
775 39         593 my $length = Rstats::Func::get_length($r, $fix_x);
776 39         220 push @$chars, $fix_x->value(($i % $length) + 1)
777             }
778 18         45 my $value = join $sep, @$chars;
779 18         70 push @$f1_elements, $value;
780             }
781            
782             # Levels
783 5         7 my $f1;
784 5         9 my $f1_levels_elements = [];
785 5 100       16 if ($x_drop) {
786 1         3 $f1_levels_elements = $f1_elements;
787 1         38 $f1 = factor($r, c_($r, @$f1_elements));
788             }
789             else {
790 4         9 my $levels = [];
791 4         9 for my $x (@xs) {
792 9         107 push @$levels, Rstats::Func::levels($r, $x)->values;
793             }
794 4         58 my $cps = Rstats::Util::cross_product($levels);
795 4         14 for my $cp (@$cps) {
796 20         32 my $value = join $sep, @$cp;
797 20         40 push @$f1_levels_elements, $value;
798             }
799 4         12 $f1_levels_elements = [sort {$a cmp $b} @$f1_levels_elements];
  32         49  
800 4         302 $f1 = factor($r, c_($r, @$f1_elements), {levels => Rstats::Func::c_($r, @$f1_levels_elements)});
801             }
802            
803 5         135 return $f1;
804             }
805              
806             sub gl {
807 5     5 0 7 my $r = shift;
808            
809 5         20 my ($x_n, $x_k, $x_length, $x_labels, $x_ordered)
810             = args_array($r, [qw/n k length labels ordered/], @_);
811            
812 5         31 my $n = $x_n->value;
813 5         27 my $k = $x_k->value;
814 5 100       65 $x_length = Rstats::Func::c_($r, $n * $k) unless defined $x_length;
815 5         37 my $length = $x_length->value;
816            
817 5         141 my $x_levels = Rstats::Func::c_($r, 1 .. $n);
818 5         140 $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         8 my $level = 1;
823 5         6 my $j = 1;
824 5         16 for (my $i = 0; $i < $length; $i++) {
825 47 100       83 if ($j > $k) {
826 13         13 $j = 1;
827 13         14 $level++;
828             }
829 47 100       85 if ($level > @$levels) {
830 3         5 $level = 1;
831             }
832 47         61 push @$x1_elements, $level;
833 47         99 $j++;
834             }
835            
836 5         396 my $x1 = Rstats::Func::c_($r, @$x1_elements);
837            
838 5 100       103 $x_labels = $x_levels unless defined $x_labels;
839 5 100       31 $x_ordered = Rstats::Func::FALSE($r) unless defined $x_ordered;
840            
841 5         23 return factor($r, $x1, {levels => $x_levels, labels => $x_labels, ordered => $x_ordered});
842             }
843              
844             sub upper_tri {
845 2     2 0 4 my $r = shift;
846            
847 2         8 my ($x1_m, $x1_diag) = args_array($r, ['m', 'diag'], @_);
848            
849 2 100       14 my $diag = defined $x1_diag ? $x1_diag->value : 0;
850            
851 2         4 my $x2_values = [];
852 2 50       34 if (Rstats::Func::is_matrix($r, $x1_m)) {
853 2         25 my $x1_dim_values = Rstats::Func::dim($r, $x1_m)->values;
854 2         11 my $rows_count = $x1_dim_values->[0];
855 2         4 my $cols_count = $x1_dim_values->[1];
856            
857 2         9 for (my $col = 0; $col < $cols_count; $col++) {
858 8         19 for (my $row = 0; $row < $rows_count; $row++) {
859 24         25 my $x2_value;
860 24 100       41 if ($diag) {
861 12 100       20 $x2_value = $col >= $row ? 1 : 0;
862             }
863             else {
864 12 100       18 $x2_value = $col > $row ? 1 : 0;
865             }
866 24         70 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         14 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 4 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         3 my $x2_values = [];
887 2 50       33 if (Rstats::Func::is_matrix($r, $x1_m)) {
888 2         26 my $x1_dim_values = Rstats::Func::dim($r, $x1_m)->values;
889 2         11 my $rows_count = $x1_dim_values->[0];
890 2         5 my $cols_count = $x1_dim_values->[1];
891            
892 2         7 for (my $col = 0; $col < $cols_count; $col++) {
893 8         19 for (my $row = 0; $row < $rows_count; $row++) {
894 24         25 my $x2_value;
895 24 100       35 if ($diag) {
896 12 100       29 $x2_value = $col <= $row ? 1 : 0;
897             }
898             else {
899 12 100       23 $x2_value = $col < $row ? 1 : 0;
900             }
901 24         96 push @$x2_values, $x2_value;
902             }
903             }
904            
905 2         28 my $x2 = matrix($r, Rstats::Func::c_logical($r, @$x2_values), $rows_count, $cols_count);
906            
907 2         14 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 5 my $r = shift;
916            
917 2         13 my $x1 = to_object($r, shift);
918            
919 2         3 my $size;
920             my $x2_values;
921 2 100       15 if (Rstats::Func::get_length($r, $x1) == 1) {
922 1         15 $size = $x1->value;
923 1         4 $x2_values = [];
924 1         7 push @$x2_values, 1 for (1 .. $size);
925             }
926             else {
927 1         5 $size = Rstats::Func::get_length($r, $x1);
928 1         7 $x2_values = $x1->values;
929             }
930            
931 2         10 my $x2 = matrix($r, 0, $size, $size);
932 2         8 for (my $i = 0; $i < $size; $i++) {
933 6         42 $x2->at($i + 1, $i + 1);
934 6         40 $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 5 my $r = shift;
963            
964 2         9 my $x1 = to_object($r, shift);
965 2         8 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         19 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         6 my $x3_dim_values = [];
975 2         13 my $x1_dim_values = $x1_dim->values;
976 2         14 my $x2_dim_values = $x2_dim->values;
977 2         9 for (my $i = 0; $i < $dim_max_length; $i++) {
978 6   100     24 my $x1_dim_value = $x1_dim_values->[$i] || 1;
979 6   100     18 my $x2_dim_value = $x2_dim_values->[$i] || 1;
980 6         13 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         3 $x3_dim_product *= $_ for @{$x3_dim_values};
  2         8  
986            
987 2         4 my $x3_values = [];
988 2         7 for (my $i = 0; $i < $x3_dim_product; $i++) {
989 576         2964 my $x3_index = Rstats::Util::pos_to_index($i, $x3_dim_values);
990 576         991 my $x1_index = [];
991 576         861 my $x2_index = [];
992 576         1629 for (my $k = 0; $k < @$x3_index; $k++) {
993 1728         2263 my $x3_i = $x3_index->[$k];
994            
995 1728   100     4560 my $x1_dim_value = $x1_dim_values->[$k] || 1;
996 1728   100     4058 my $x2_dim_value = $x2_dim_values->[$k] || 1;
997              
998 1728         3635 my $x1_ind = int(($x3_i - 1)/$x2_dim_value) + 1;
999 1728         2767 push @$x1_index, $x1_ind;
1000 1728         2564 my $x2_ind = $x3_i - $x2_dim_value * ($x1_ind - 1);
1001 1728         4933 push @$x2_index, $x2_ind;
1002             }
1003 576         3401 my $x1_value = $x1->value(@$x1_index);
1004 576         3593 my $x2_value = $x2->value(@$x2_index);
1005 576         16370 my $x3_value = multiply($r, $x1_value, $x2_value);
1006 576         5753 push @$x3_values, $x3_value;
1007             }
1008            
1009 2         5712 my $x3 = array($r, c_($r, @$x3_values), Rstats::Func::c_($r, @$x3_dim_values));
1010            
1011 2         1870 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       12 ($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         10 my $x2_dim = Rstats::Func::dim($r, $x2);
1024 1         3 my $x3_dim = [@{$x1_dim->values}, @{$x2_dim->values}];
  1         8  
  1         7  
1025            
1026 1         5 my $indexs = [];
1027 1         2 for my $x3_d (@$x3_dim) {
1028 4         12 push @$indexs, [1 .. $x3_d];
1029             }
1030 1         78 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         3 for my $pos (@$poses) {
1035 24         49 my $pos_tmp = [@$pos];
1036 24         54 my $x1_pos = [splice @$pos_tmp, 0, $x1_dim_length];
1037 24         35 my $x2_pos = $pos_tmp;
1038 24         135 my $x1_value = $x1->value(@$x1_pos);
1039 24         136 my $x2_value = $x2->value(@$x2_pos);
1040 24         47 my $x3_value = $x1_value * $x2_value;
1041 24         73 push @$x3_values, $x3_value;
1042             }
1043            
1044 1         435 my $x3 = array($r, c_($r, @$x3_values), Rstats::Func::c_($r, @$x3_dim));
1045            
1046 1         97 return $x3;
1047             }
1048              
1049              
1050              
1051             sub sub {
1052 2     2 0 5 my $r = shift;
1053            
1054 2         11 my ($x1_pattern, $x1_replacement, $x1_x, $x1_ignore_case)
1055             = args_array($r, ['pattern', 'replacement', 'x', 'ignore.case'], @_);
1056            
1057 2         14 my $pattern = $x1_pattern->value;
1058 2         11 my $replacement = $x1_replacement->value;
1059 2 100       12 my $ignore_case = defined $x1_ignore_case ? $x1_ignore_case->value : 0;
1060            
1061 2         4 my $x2_values = [];
1062 2         4 for my $x (@{$x1_x->values}) {
  2         52  
1063 6 100       12 if (!defined $x) {
1064 2         4 push @$x2_values, undef;
1065             }
1066             else {
1067 4 100       10 if ($ignore_case) {
1068 2         18 $x =~ s/$pattern/$replacement/i;
1069             }
1070             else {
1071 2         28 $x =~ s/$pattern/$replacement/;
1072             }
1073 4         13 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         8 return $x2;
1081             }
1082              
1083             sub gsub {
1084 2     2 0 6 my $r = shift;
1085            
1086 2         11 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         12 my $replacement = $x1_replacement->value;
1091 2 100       13 my $ignore_case = defined $x1_ignore_case ? $x1_ignore_case->value : 0;
1092            
1093 2         5 my $x2_values = [];
1094 2         4 for my $x (@{$x1_x->values}) {
  2         10  
1095 6 100       17 if (!defined $x) {
1096 2         3 push @$x2_values, $x;
1097             }
1098             else {
1099 4 100       9 if ($ignore_case) {
1100 2         19 $x =~ s/$pattern/$replacement/gi;
1101             }
1102             else {
1103 2         21 $x =~ s/$pattern/$replacement/g;
1104             }
1105 4         11 push @$x2_values, $x;
1106             }
1107             }
1108            
1109 2         35 my $x2 = Rstats::Func::c_character($r, @$x2_values);
1110 2         14 Rstats::Func::copy_attrs_to($r, $x1_x, $x2);
1111            
1112 2         10 return $x2;
1113             }
1114              
1115             sub grep {
1116 2     2 0 5 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       13 my $ignore_case = defined $x1_ignore_case ? $x1_ignore_case->value : 0;
1122            
1123 2         5 my $x2_values = [];
1124 2         11 my $x1_x_values = $x1_x->values;
1125 2         10 for (my $i = 0; $i < @$x1_x_values; $i++) {
1126 6         11 my $x = $x1_x_values->[$i];
1127            
1128 6 100       17 unless (!defined $x) {
1129 4 100       10 if ($ignore_case) {
1130 2 50       17 if ($x =~ /$pattern/i) {
1131 2         14 push @$x2_values, $i + 1;
1132             }
1133             }
1134             else {
1135 2 100       17 if ($x =~ /$pattern/) {
1136 1         6 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 238 my $r = shift;
1147 127         230 my $seq_str = shift;
1148              
1149 127         192 my $by;
1150             my $mode;
1151 127 100       480 if ($seq_str =~ s/^(.+)\*//) {
1152 1         3 $by = $1;
1153             }
1154            
1155 127         323 my $from;
1156             my $to;
1157 127 50       745 if ($seq_str =~ /([^\:]+)(?:\:(.+))?/) {
1158 127         281 $from = $1;
1159 127         263 $to = $2;
1160 127 50       341 $to = $from unless defined $to;
1161             }
1162            
1163 127         704 my $vector = seq($r,{from => $from, to => $to, by => $by});
1164            
1165 127         5024 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         13 my @values;
1176 1         5 for my $col (1 .. $ncol) {
1177 4         10 push @values, ($col) x $nrow;
1178             }
1179            
1180 1         220 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         7 my ($x1_old, $x1_new, $x1_x) = args_array($r, ['old', 'new', 'x'], @_);
1187            
1188 1         189 my $old = $x1_old->value;
1189 1         7 my $new = $x1_new->value;
1190            
1191 1         3 my $x2_values = [];
1192 1         2 for my $x (@{$x1_x->values}) {
  1         6  
1193 3 100       10 if (!defined $x) {
1194 1         3 push @$x2_values, $x;
1195             }
1196             else {
1197 2         4 $old =~ s#/#\/#;
1198 2         4 $new =~ s#/#\/#;
1199 2         116 eval "\$x =~ tr/$old/$new/";
1200 2 50       9 Carp::croak $@ if $@;
1201 2         5 push @$x2_values, "$x";
1202             }
1203             }
1204            
1205 1         100 my $x2 = Rstats::Func::c_character($r, @$x2_values);
1206 1         8 Rstats::Func::copy_attrs_to($r, $x1_x, $x2);
1207            
1208 1         5 return $x2;
1209             }
1210              
1211             sub charmatch {
1212 5     5 0 11 my $r = shift;
1213            
1214 5         20 my ($x1_x, $x1_table) = args_array($r, ['x', 'table'], @_);
1215            
1216 5 50 33     32 die "Error in charmatch() : Not implemented"
1217             unless $x1_x->get_type eq 'character' && $x1_table->get_type eq 'character';
1218            
1219 5         13 my $x2_values = [];
1220 5         8 for my $x1_x_value (@{$x1_x->values}) {
  5         25  
1221 6         12 my $x1_x_char = $x1_x_value;
1222 6         10 my $x1_x_char_q = quotemeta($x1_x_char);
1223 6         10 my $match_count;
1224             my $match_pos;
1225 6         29 my $x1_table_values = $x1_table->values;
1226 6         40 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       106 if ($x1_table_char =~ /$x1_x_char_q/) {
1229 10         15 $match_count++;
1230 10         54 $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         14 push @$x2_values, $match_pos + 1;
1238             }
1239             elsif ($match_count > 1) {
1240 2         7 push @$x2_values, 0;
1241             }
1242             }
1243            
1244 5         82 return Rstats::Func::c_double($r, @$x2_values);
1245             }
1246              
1247              
1248              
1249             sub nrow {
1250 5     5 0 14 my $r = shift;
1251            
1252 5         10 my $x1 = shift;
1253            
1254 5 100       63 if (Rstats::Func::is_data_frame($r, $x1)) {
    100          
1255 1         31 return Rstats::Func::c_($r, $x1->{row_length});
1256             }
1257             elsif (Rstats::Func::is_list($r, $x1)) {
1258 1         8 return Rstats::Func::NULL($r);
1259             }
1260             else {
1261 3         37 return Rstats::Func::c_($r, Rstats::Func::dim($r, $x1)->values->[0]);
1262             }
1263             }
1264              
1265             sub is_element {
1266 2     2 0 5 my $r = shift;
1267            
1268 2         12 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1269            
1270 2 50       11 Carp::croak "mode is diffrence" if $x1->get_type ne $x2->get_type;
1271            
1272 2         13 my $type = $x1->get_type;
1273 2         13 my $x1_values = $x1->values;
1274 2         12 my $x2_values = $x2->values;
1275 2         5 my $x3_values = [];
1276 2         7 for my $x1_value (@$x1_values) {
1277 8         10 my $match;
1278 8         11 for my $x2_value (@$x2_values) {
1279 18 50 66     91 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       26 if ($x1_value == $x2_value) {
1287 3         6 $match = 1;
1288 3         4 last;
1289             }
1290             }
1291             elsif ($type eq 'complex') {
1292 9 100 66     50 if ($x1_value->{re} == $x2_value->{re} && $x1_value->{im} == $x2_value->{im}) {
1293 3         5 $match = 1;
1294 3         6 last;
1295             }
1296             }
1297             }
1298 8 100       24 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 6 my $r = shift;
1306            
1307 3         15 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1308            
1309 3 50       17 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         29 my $x4 = Rstats::Func::sort($r, $x2);
1313            
1314 3 100       59 return Rstats::Func::FALSE($r) if Rstats::Func::get_length($r, $x3) ne Rstats::Func::get_length($r, $x4);
1315            
1316 2         4 my $not_equal;
1317 2         30 my $x3_elements = Rstats::Func::decompose($r, $x3);
1318 2         29 my $x4_elements = Rstats::Func::decompose($r, $x4);
1319 2         21 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       52 return $not_equal ? Rstats::Func::FALSE($r) : TRUE($r);
1327             }
1328              
1329             sub setdiff {
1330 1     1 0 2 my $r = shift;
1331            
1332 1         8 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         21 my $x1_elements = Rstats::Func::decompose($r, $x1);
1337 1         13 my $x2_elements = Rstats::Func::decompose($r, $x2);
1338 1         3 my $x3_elements = [];
1339 1         3 for my $x1_element (@$x1_elements) {
1340 4         6 my $match;
1341 4         8 for my $x2_element (@$x2_elements) {
1342 7 100       21 if ($x1_element == $x2_element) {
1343 2         3 $match = 1;
1344 2         5 last;
1345             }
1346             }
1347 4 100       20 push @$x3_elements, $x1_element unless $match;
1348             }
1349              
1350 1         29 return Rstats::Func::c_($r, @$x3_elements);
1351             }
1352              
1353             sub intersect {
1354 1     1 0 3 my $r = shift;
1355            
1356 1         5 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         19 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         10 for my $x2_element (@$x2_elements) {
1365 16 100       45 if ($x1_element == $x2_element) {
1366 2         12 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       8 Carp::croak "mode is diffrence" if $x1->get_type ne $x2->get_type;
1380            
1381 1         20 my $x3 = Rstats::Func::c_($r, $x1, $x2);
1382 1         5 my $x4 = unique($r, $x3);
1383            
1384 1         21 return $x4;
1385             }
1386              
1387             sub diff {
1388 2     2 0 5 my $r = shift;
1389            
1390 2         12 my $x1 = to_object($r, shift);
1391            
1392 2         8 my $x2_elements = [];
1393 2         56 my $x1_elements = Rstats::Func::decompose($r, $x1);
1394 2         22 for (my $i = 0; $i < Rstats::Func::get_length($r, $x1) - 1; $i++) {
1395 5         14 my $x1_element1 = $x1_elements->[$i];
1396 5         11 my $x1_element2 = $x1_elements->[$i + 1];
1397 5         21 my $x2_element = $x1_element2 - $x1_element1;
1398 5         101 push @$x2_elements, $x2_element;
1399             }
1400 2         52 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1401 2         21 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1402            
1403 2         43 return $x2;
1404             }
1405              
1406             sub nchar {
1407 1     1 0 4 my $r = shift;
1408 1         7 my $x1 = to_object($r, shift);
1409            
1410 1 50       9 if ($x1->get_type eq 'character') {
1411 1         3 my $x2_elements = [];
1412 1         3 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  1         25  
1413 3 100       54 if (Rstats::Func::is_na($r, $x1_element)) {
1414 1         10 push @$x2_elements, $x1_element;
1415             }
1416             else {
1417 2         7 my $x2_element = Rstats::Func::c_integer($r, CORE::length Rstats::Func::value($r, $x1_element));
1418 2         19 push @$x2_elements, $x2_element;
1419             }
1420             }
1421 1         109 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1422 1         29 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1423            
1424 1         15 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         7 my $x1 = to_object($r, shift);
1435            
1436 1 50       9 if ($x1->get_type eq 'character') {
1437 1         3 my $x2_elements = [];
1438 1         3 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  1         23  
1439 3 100       63 if (Rstats::Func::is_na($r, $x1_element)) {
1440 1         8 push @$x2_elements, $x1_element;
1441             }
1442             else {
1443 2         8 my $x2_element = Rstats::Func::c_character($r, lc Rstats::Func::value($r, $x1_element));
1444 2         24 push @$x2_elements, $x2_element;
1445             }
1446             }
1447 1         39 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1448 1         11 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1449            
1450 1         14 return $x2;
1451             }
1452             else {
1453 0         0 return $x1;
1454             }
1455             }
1456              
1457             sub toupper {
1458 1     1 0 22 my $r = shift;
1459            
1460 1         7 my $x1 = to_object($r, shift);
1461            
1462 1 50       9 if ($x1->get_type eq 'character') {
1463 1         3 my $x2_elements = [];
1464 1         3 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  1         25  
1465 3 100       64 if (Rstats::Func::is_na($r, $x1_element)) {
1466 1         9 push @$x2_elements, $x1_element;
1467             }
1468             else {
1469 2         9 my $x2_element = Rstats::Func::c_character($r, uc Rstats::Func::value($r, $x1_element));
1470 2         27 push @$x2_elements, $x2_element;
1471             }
1472             }
1473 1         38 my $x2 = Rstats::Func::c_($r, @$x2_elements);
1474 1         10 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1475            
1476 1         13 return $x2;
1477             }
1478             else {
1479 0         0 return $x1;
1480             }
1481             }
1482              
1483             sub match {
1484 1     1 0 4 my $r = shift;
1485            
1486 1         9 my ($x1, $x2) = (to_object($r, shift), to_object($r, shift));
1487            
1488 1         25 my $x1_elements = Rstats::Func::decompose($r, $x1);
1489 1         27 my $x2_elements = Rstats::Func::decompose($r, $x2);
1490 1         4 my @matches;
1491 1         5 for my $x1_element (@$x1_elements) {
1492 4         8 my $i = 1;
1493 4         8 my $match;
1494 4         11 for my $x2_element (@$x2_elements) {
1495 15 100       59 if ($x1_element == $x2_element) {
1496 2         6 $match = 1;
1497 2         6 last;
1498             }
1499 13         82 $i++;
1500             }
1501 4 100       21 if ($match) {
1502 2         8 push @matches, $i;
1503             }
1504             else {
1505 2         6 push @matches, undef;
1506             }
1507             }
1508            
1509 1         93 return Rstats::Func::c_double($r, @matches);
1510             }
1511              
1512              
1513              
1514             sub append {
1515 3     3 0 5 my $r = shift;
1516            
1517 3         14 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         15 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         30 my $after = $x_after->value;
1525            
1526 3         60 my $x1_elements = Rstats::Func::decompose($r, $x1);
1527 3         28 my $x2_elements = Rstats::Func::decompose($r, $x2);
1528 3         9 my @x3_elements = @$x1_elements;
1529 3         9 splice @x3_elements, $after, 0, @$x2_elements;
1530            
1531 3         90 my $x3 = Rstats::Func::c_($r, @x3_elements);
1532            
1533 3         57 return $x3;
1534             }
1535              
1536              
1537              
1538             sub cbind {
1539 4     4 0 9 my $r = shift;
1540            
1541 4         12 my @xs = @_;
1542              
1543 4 50       22 return Rstats::Func::NULL($r) unless @xs;
1544            
1545 4 100       103 if (Rstats::Func::is_data_frame($r, $xs[0])) {
1546             # Check row count
1547 2         5 my $first_row_length;
1548             my $different;
1549 2         8 for my $x (@xs) {
1550 4 100       12 if ($first_row_length) {
1551 2 50       12 $different = 1 if $x->{row_length} != $first_row_length;
1552             }
1553             else {
1554 2         8 $first_row_length = $x->{row_length};
1555             }
1556             }
1557 2 50       10 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         6 for my $x (@xs) {
1563 4         67 my $names = Rstats::Func::names($r, $x)->values;
1564 4         32 for my $name (@$names) {
1565 6         38 push @data_frame_args, $name, $x->getin($name);
1566             }
1567             }
1568 2         21 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         6 my $x2_elements = [];
1576 2         7 for my $_x (@xs) {
1577            
1578 6         23 my $x1 = to_object($r, $_x);
1579 6         58 my $x1_dim_elements = Rstats::Func::decompose($r, Rstats::Func::dim($r, $x1));
1580            
1581 6         16 my $row_count;
1582 6 50       74 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         34 $row_count = $x1->dim_as_array->values->[0];
1588 6         36 $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       50 $row_count_needed = $row_count unless defined $row_count_needed;
1595 6 50       48 Carp::croak "Row count is different" if $row_count_needed ne $row_count;
1596            
1597 6         10 push @$x2_elements, @{Rstats::Func::decompose($r, $x1)};
  6         128  
1598             }
1599 2         110 my $matrix = matrix($r, c_($r, @$x2_elements), $row_count_needed, $col_count_total);
1600            
1601 2         49 return $matrix;
1602             }
1603             }
1604              
1605             sub ceiling {
1606 2     2 0 5 my $r = shift;
1607 2         3 my $_x1 = shift;
1608            
1609 2         8 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         3 @{Rstats::Func::decompose($r, $x1)};
  2         38  
1613            
1614 2         65 my $x2 = Rstats::Func::c_($r, @x2_elements);
1615 2         21 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1616            
1617 2         47 Rstats::Func::mode($r, $x2, 'double');
1618            
1619 2         33 return $x2;
1620             }
1621              
1622             sub colMeans {
1623 1     1 0 6 my $r = shift;
1624 1         4 my $x1 = shift;
1625            
1626 1         25 my $dim_values = Rstats::Func::dim($r, $x1)->values;
1627 1 50       14 if (@$dim_values == 2) {
1628 1         5 my $x1_values = [];
1629 1         8 for my $row (1 .. $dim_values->[0]) {
1630 4         9 my $x1_value = 0;
1631 4         45 $x1_value += $x1->value($row, $_) for (1 .. $dim_values->[1]);
1632 4         21 push @$x1_values, $x1_value / $dim_values->[1];
1633             }
1634 1         56 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 2 my $r = shift;
1643 1         2 my $x1 = shift;
1644            
1645 1         15 my $dim_values = Rstats::Func::dim($r, $x1)->values;
1646 1 50       8 if (@$dim_values == 2) {
1647 1         3 my $x1_values = [];
1648 1         4 for my $row (1 .. $dim_values->[0]) {
1649 4         7 my $x1_value = 0;
1650 4         31 $x1_value += $x1->value($row, $_) for (1 .. $dim_values->[1]);
1651 4         12 push @$x1_values, $x1_value;
1652             }
1653 1         44 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 2 my $r = shift;
1666            
1667 1         6 my $x1 = to_object($r, shift);
1668            
1669 1 50       9 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         2 my @x2_elements;
1675 1         19 my $x1_elements = Rstats::Func::decompose($r, $x1);
1676 1         3 my $max = shift @$x1_elements;
1677 1         3 push @x2_elements, $max;
1678 1         4 for my $element (@$x1_elements) {
1679            
1680 3 50       64 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     26 if ($element > $max && !Rstats::Func::is_nan($r, $max)) {
1687 2         6 $max = $element;
1688             }
1689 3         20 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 3 my $r = shift;
1697            
1698 1         5 my $x1 = to_object($r, shift);
1699            
1700 1 50       8 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         4 push @x2_elements, $min;
1709 1         4 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     25 if ($element < $min && !Rstats::Func::is_nan($r, $min)) {
1717 2         5 $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 582 my $r = shift;
1729            
1730 368         522 my $names = shift;
1731 368 100       1152 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
1732 368         499 my @args;
1733 368         1112 for (my $i = 0; $i < @$names; $i++) {
1734 1460         2240 my $name = $names->[$i];
1735 1460         1675 my $arg;
1736 1460 100       4224 if (exists $opt->{$name}) {
    100          
1737 140         615 $arg = to_object($r, delete $opt->{$name});
1738             }
1739             elsif ($i < @_) {
1740 592         3138 $arg = to_object($r, $_[$i]);
1741             }
1742 1460         4219 push @args, $arg;
1743             }
1744            
1745 368         1148 Carp::croak "unused argument ($_)" for keys %$opt;
1746            
1747 368         1282 return @args;
1748             }
1749              
1750             sub complex {
1751 39     39 0 63 my $r = shift;
1752              
1753 39         147 my ($x1_re, $x1_im, $x1_mod, $x1_arg) = args_array($r, ['re', 'im', 'mod', 'arg'], @_);
1754            
1755 39 100       267 $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         69 my $x2_elements = [];
1759             # Create complex from mod and arg
1760 39 100 100     378 if (Rstats::Func::get_length($r, $x1_mod) || Rstats::Func::get_length($r, $x1_arg)) {
1761 3         13 my $x1_mod_length = Rstats::Func::get_length($r, $x1_mod);
1762 3         13 my $x1_arg_length = Rstats::Func::get_length($r, $x1_arg);
1763 3 100       8 my $longer_length = $x1_mod_length > $x1_arg_length ? $x1_mod_length : $x1_arg_length;
1764            
1765 3         23 my $x1_mod_elements = Rstats::Func::decompose($r, $x1_mod);
1766 3         24 my $x1_arg_elements = Rstats::Func::decompose($r, $x1_arg);
1767 3         10 for (my $i = 0; $i < $longer_length; $i++) {
1768 3         6 my $x_mod = $x1_mod_elements->[$i];
1769 3 100       16 $x_mod = Rstats::Func::c_double($r, 1) unless defined $x_mod;
1770 3         13 my $x_arg = $x1_arg_elements->[$i];
1771 3 100       18 $x_arg = Rstats::Func::c_double($r, 0) unless defined $x_arg;
1772            
1773 3         53 my $x_re = $x_mod * Rstats::Func::cos($r, $x_arg);
1774 3         62 my $x_im = $x_mod * Rstats::Func::sin($r, $x_arg);
1775            
1776 3         23 my $x2_element = Rstats::Func::complex($r, $x_re, $x_im);
1777 3         39 push @$x2_elements, $x2_element;
1778             }
1779             }
1780             # Create complex from re and im
1781             else {
1782 36 50 33     390 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         523 my $x1_re_elements = Rstats::Func::decompose($r, $x1_re);
1786 36         337 my $x1_im_elements = Rstats::Func::decompose($r, $x1_im);
1787 36         208 for (my $i = 0; $i < Rstats::Func::get_length($r, $x1_im); $i++) {
1788 40         50 my $x_re;
1789 40 100       92 if (defined $x1_re_elements->[$i]) {
1790 39         73 $x_re = $x1_re_elements->[$i];
1791             }
1792             else {
1793 1         10 $x_re = Rstats::Func::c_double($r, 0);
1794             }
1795 40         56 my $x_im = $x1_im_elements->[$i];
1796 40         92 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         511 push @$x2_elements, $x2_element;
1801             }
1802             }
1803            
1804 39         793 return Rstats::Func::c_($r, @$x2_elements);
1805             }
1806              
1807              
1808             sub floor {
1809 2     2 0 4 my $r = shift;
1810            
1811 2         5 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         5 @{Rstats::Func::decompose($r, $x1)};
  2         38  
1818              
1819 2         62 my $x2 = Rstats::Func::c_($r, @x2_elements);
1820 2         22 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1821 2         46 Rstats::Func::mode($r, $x2, 'double');
1822            
1823 2         32 return $x2;
1824             }
1825              
1826             sub head {
1827 5     5 0 12 my $r = shift;
1828            
1829 5         29 my ($x1, $x_n) = args_array($r, ['x1', 'n'], @_);
1830            
1831 5 100       31 my $n = defined $x_n ? $x_n->value : 6;
1832            
1833 5 100       57 if (Rstats::Func::is_data_frame($r, $x1)) {
1834 2 50       14 my $max = $x1->{row_length} < $n ? $x1->{row_length} : $n;
1835            
1836 2         14 my $x_range = Rstats::Func::C_($r, "1:$max");
1837 2         25 my $x2 = $x1->get($x_range, Rstats::Func::NULL($r));
1838            
1839 2         16 return $x2;
1840             }
1841             else {
1842 3         58 my $x1_elements = Rstats::Func::decompose($r, $x1);
1843 3 100       21 my $max = Rstats::Func::get_length($r, $x1) < $n ? Rstats::Func::get_length($r, $x1) : $n;
1844 3         6 my @x2_elements;
1845 3         10 for (my $i = 0; $i < $max; $i++) {
1846 12         32 push @x2_elements, $x1_elements->[$i];
1847             }
1848            
1849 3         69 my $x2 = Rstats::Func::c_($r, @x2_elements);
1850 3         23 Rstats::Func::copy_attrs_to($r, $x1, $x2);
1851            
1852 3         39 return $x2;
1853             }
1854             }
1855              
1856             sub i_ {
1857 119     119 0 197 my $r = shift;
1858            
1859 119         1527 my $i = Rstats::Func::c_complex($r, {re => 0, im => 1});
1860            
1861 119         2171 return Rstats::Func::c_($r, $i);
1862             }
1863              
1864             sub ifelse {
1865 1     1 0 3 my $r = shift;
1866            
1867 1         3 my ($_x1, $value1, $value2) = @_;
1868            
1869 1         4 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         6 local $_ = $x1_value;
1874 3 100       7 if ($x1_value) {
1875 2         6 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 11 my $r = shift;
1889              
1890 6         13 my @args = grep { !Rstats::Func::is_null($r, $_) } @_;
  7         84  
1891            
1892 6         84 my $x1 = Rstats::Func::c_($r, @args);
1893            
1894 6 100       39 unless (Rstats::Func::get_length($r, $x1)) {
1895 1         184 Carp::carp 'no non-missing arguments to max; returning -Inf';
1896 1         132 return -(Rstats::Func::Inf($r));
1897             }
1898            
1899 5         79 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       192 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         4 $max = $element;
1908             }
1909 13 100 66     227 if (!Rstats::Func::is_nan($r, $max) && Rstats::Func::value($r, $element > $max)) {
1910 11         96 $max = $element;
1911             }
1912             }
1913            
1914 4         89 return Rstats::Func::c_($r, $max);
1915             }
1916              
1917             sub mean {
1918 4     4 0 8 my $r = shift;
1919            
1920 4         14 my $x1 = to_object($r, shift);
1921            
1922 4         145 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 10 my $r = shift;
1929            
1930 6         13 my @args = grep { !Rstats::Func::is_null($r, $_) } @_;
  7         68  
1931            
1932 6         83 my $x1 = Rstats::Func::c_($r, @args);
1933            
1934 6 100       42 unless (Rstats::Func::get_length($r, $x1)) {
1935 1         209 Carp::carp 'no non-missing arguments to min; returning Inf';
1936 1         108 return Rstats::Func::Inf($r);
1937             }
1938            
1939 5         88 my $x1_elements = Rstats::Func::decompose($r, $x1);
1940 5         9 my $min = shift @$x1_elements;
1941 5         13 for my $element (@$x1_elements) {
1942            
1943 14 100       181 if (Rstats::Func::is_na($r, $element)) {
    100          
1944 1         17 return Rstats::Func::NA($r);
1945             }
1946             elsif (Rstats::Func::is_nan($r, $element)) {
1947 2         4 $min = $element;
1948             }
1949 13 50 66     225 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 9 my $r = shift;
1959 5 100       23 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
1960 5         12 my @xs = map { to_object($r, $_) } @_;
  7         39  
1961            
1962 5         9 my @xs_values;
1963 5         13 for my $x (@xs) {
1964 7         50 push @xs_values, $x->values;
1965             }
1966              
1967 5   66     43 my $decreasing = $opt->{decreasing} || Rstats::Func::FALSE($r);
1968            
1969 5         13 my @pos_vals;
1970 5         9 for my $i (0 .. @{$xs_values[0]} - 1) {
  5         27  
1971 24         78 my $pos_val = {pos => $i + 1};
1972 24         65 $pos_val->{val} = [];
1973 24         76 push @{$pos_val->{val}}, $xs_values[$_][$i] for (0 .. @xs_values);
  108         339  
1974 24         63 push @pos_vals, $pos_val;
1975             }
1976            
1977             my @sorted_pos_values = !$decreasing
1978             ? sort {
1979 21         26 my $comp;
1980 21         65 for (my $i = 0; $i < @xs_values; $i++) {
1981 24         52 $comp = $a->{val}[$i] <=> $b->{val}[$i];
1982 24 100       63 last if $comp != 0;
1983             }
1984             $comp;
1985             } @pos_vals
1986             : sort {
1987 5 100       29 my $comp;
  16         31  
1988 16         65 for (my $i = 0; $i < @xs_values; $i++) {
1989 19         58 $comp = $b->{val}[$i] <=> $a->{val}[$i];
1990 19 100       79 last if $comp != 0;
1991             }
1992             $comp;
1993             } @pos_vals;
1994 5         13 my @orders = map { $_->{pos} } @sorted_pos_values;
  24         62  
1995            
1996 5         440 return Rstats::Func::c_($r, @orders);
1997             }
1998              
1999             # TODO
2000             # na.last
2001             sub rank {
2002 1     1 0 2 my $r = shift;
2003            
2004 1 50       7 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2005 1         5 my $x1 = to_object($r, shift);
2006 1         3 my $decreasing = $opt->{decreasing};
2007            
2008 1         7 my $x1_values = $x1->values;
2009            
2010 1         4 my @pos_vals;
2011 1         17 push @pos_vals, {pos => $_ + 1, value => $x1_values->[$_]} for (0 .. @$x1_values - 1);
2012 1         8 my @sorted_pos_values = sort { $a->{value} <=> $b->{value} } @pos_vals;
  13         23  
2013            
2014             # Rank
2015 1         6 for (my $i = 0; $i < @sorted_pos_values; $i++) {
2016 7         21 $sorted_pos_values[$i]{rank} = $i + 1;
2017             }
2018            
2019             # Average rank
2020 1         3 my $element_info = {};
2021 1         3 for my $sorted_pos_value (@sorted_pos_values) {
2022 7         11 my $value = $sorted_pos_value->{value};
2023 7   100     27 $element_info->{$value} ||= {};
2024 7         15 $element_info->{$value}{rank_total} += $sorted_pos_value->{rank};
2025 7         14 $element_info->{$value}{rank_count}++;
2026             }
2027            
2028 1         3 for my $sorted_pos_value (@sorted_pos_values) {
2029 7         12 my $value = $sorted_pos_value->{value};
2030             $sorted_pos_value->{rank_average}
2031 7         17 = $element_info->{$value}{rank_total} / $element_info->{$value}{rank_count};
2032             }
2033            
2034 1         3 my @sorted_pos_values2 = sort { $a->{pos} <=> $b->{pos} } @sorted_pos_values;
  14         20  
2035 1         3 my @rank = map { $_->{rank_average} } @sorted_pos_values2;
  7         13  
2036            
2037 1         93 return Rstats::Func::c_($r, @rank);
2038             }
2039              
2040             sub paste {
2041 3     3 0 8 my $r = shift;
2042            
2043 3 100       18 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2044 3         9 my $sep = $opt->{sep};
2045 3 100       11 $sep = ' ' unless defined $sep;
2046            
2047 3         8 my $str = shift;
2048 3         7 my $x1 = shift;
2049            
2050 3         21 my $x1_values = $x1->values;
2051 3         10 my $x2_values = [];
2052 3         68 push @$x2_values, "$str$sep$_" for @$x1_values;
2053            
2054 3         130 return Rstats::Func::c_($r, @$x2_values);
2055             }
2056              
2057             sub pmax {
2058 1     1 0 3 my $r = shift;
2059            
2060 1         3 my @vs = @_;
2061            
2062 1         2 my @maxs;
2063 1         2 for my $v (@vs) {
2064 2         46 my $elements = Rstats::Func::decompose($r, $v);
2065 2         9 for (my $i = 0; $i <@$elements; $i++) {
2066 8 100 100     39 $maxs[$i] = $elements->[$i]
2067             if !defined $maxs[$i] || $elements->[$i] > $maxs[$i]
2068             }
2069             }
2070            
2071 1         35 return Rstats::Func::c_($r, @maxs);
2072             }
2073              
2074             sub pmin {
2075 1     1 0 3 my $r = shift;
2076            
2077 1         3 my @vs = @_;
2078            
2079 1         2 my @mins;
2080 1         4 for my $v (@vs) {
2081 2         37 my $elements = Rstats::Func::decompose($r, $v);
2082 2         8 for (my $i = 0; $i <@$elements; $i++) {
2083 8 100 100     49 $mins[$i] = $elements->[$i]
2084             if !defined $mins[$i] || $elements->[$i] < $mins[$i];
2085             }
2086             }
2087            
2088 1         27 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         6 my $min = min($r, $x1);
2099 1         8 my $max = max($r, $x1);
2100            
2101 1         21 return Rstats::Func::c_($r, $min, $max);
2102             }
2103              
2104             sub rbind {
2105 2     2 0 7 my $r = shift;
2106 2         8 my (@xs) = @_;
2107            
2108 2 50       11 return Rstats::Func::NULL($r) unless @xs;
2109            
2110 2 100       29 if (Rstats::Func::is_data_frame($r, $xs[0])) {
2111            
2112             # Check names
2113 1         3 my $first_names;
2114 1         3 for my $x (@xs) {
2115 2 100       8 if ($first_names) {
2116 1         18 my $names = Rstats::Func::names($r, $x)->values;
2117 1         7 my $different;
2118 1 50       20 $different = 1 if @$first_names != @$names;
2119 1         7 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       8 Carp::croak "rbind require same names having data frame"
2123             if $different;
2124             }
2125             else {
2126 1         19 $first_names = Rstats::Func::names($r, $x)->values;
2127             }
2128             }
2129            
2130             # Create new vectors
2131 1         3 my @new_vectors;
2132 1         4 for my $name (@$first_names) {
2133 2         4 my @vectors;
2134 2         5 for my $x (@xs) {
2135 4         26 my $v = $x->getin($name);
2136 4 100       92 if (Rstats::Func::is_factor($r, $v)) {
2137 2         177 push @vectors, Rstats::Func::as_character($r, $v);
2138             }
2139             else {
2140 2         23 push @vectors, $v;
2141             }
2142             }
2143 2         51 my $new_vector = Rstats::Func::c_($r, @vectors);
2144 2         15 push @new_vectors, $new_vector;
2145             }
2146            
2147             # Create new data frame
2148 1         4 my @data_frame_args;
2149 1         6 for (my $i = 0; $i < @$first_names; $i++) {
2150 2         9 push @data_frame_args, $first_names->[$i], $new_vectors[$i];
2151             }
2152 1         6 my $data_frame = Rstats::Func::data_frame($r, @data_frame_args);
2153            
2154 1         47 return $data_frame;
2155             }
2156             else {
2157 1         6 my $matrix = cbind($r, @xs);
2158            
2159 1         8 return Rstats::Func::t($r, $matrix);
2160             }
2161             }
2162              
2163             sub rep {
2164 11     11 0 16 my $r = shift;
2165            
2166 11         40 my ($x1, $x_times) = args_array($r, ['x1', 'times'], @_);
2167            
2168 11 50       79 my $times = defined $x_times ? $x_times->value : 1;
2169            
2170 11         27 my $elements = [];
2171 11         32 push @$elements, @{Rstats::Func::decompose($r, $x1)} for 1 .. $times;
  33         347  
2172 11         241 my $x2 = Rstats::Func::c_($r, @$elements);
2173            
2174 11         141 return $x2;
2175             }
2176              
2177             sub replace {
2178 3     3 0 6 my $r = shift;
2179            
2180 3         10 my $x1 = to_object($r, shift);
2181 3         10 my $x2 = to_object($r, shift);
2182 3         13 my $x3 = to_object($r, shift);
2183            
2184 3         102 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         22 my $x2_element_hash = Rstats::Func::to_string($r, $x2_element);
2189            
2190 9         27 $x2_elements_h->{$x2_element_hash}++;
2191             Carp::croak "replace second argument can't have duplicate number"
2192 9 50       30 if $x2_elements_h->{$x2_element_hash} > 1;
2193             }
2194 3         35 my $x3_elements = Rstats::Func::decompose($r, $x3);
2195 3         7 my $x3_length = @{$x3_elements};
  3         7  
2196            
2197 3         5 my $x4_elements = [];
2198 3         10 my $replace_count = 0;
2199 3         13 for (my $i = 0; $i < @$x1_elements; $i++) {
2200 30         307 my $hash = Rstats::Func::to_string($r, Rstats::Func::c_double($r, $i + 1));
2201 30 100       153 if ($x2_elements_h->{$hash}) {
2202 9         21 push @$x4_elements, $x3_elements->[$replace_count % $x3_length];
2203 9         32 $replace_count++;
2204             }
2205             else {
2206 21         78 push @$x4_elements, $x1_elements->[$i];
2207             }
2208             }
2209            
2210 3         524 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         3 my @x2_elements = reverse @{Rstats::Func::decompose($r, $x1)};
  1         24  
2220 1         33 my $x2 = Rstats::Func::c_($r, @x2_elements);
2221 1         13 Rstats::Func::copy_attrs_to($r, $x1, $x2);
2222            
2223 1         33 return $x2;
2224             }
2225              
2226             sub rnorm {
2227 1     1 0 3 my $r = shift;
2228            
2229             # Option
2230 1 50       5 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2231            
2232             # Count
2233 1         2 my ($count, $mean, $sd) = @_;
2234 1 50       5 Carp::croak "rnorm count should be bigger than 0"
2235             if $count < 1;
2236            
2237             # Mean
2238 1 50       14 $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         1 my @x1_elements;
2245            
2246 1         13 my $pi = $r->pi->value;
2247 1         6 for (1 .. $count) {
2248 100         225 my ($rand1, $rand2) = (rand, rand);
2249 100         245 while ($rand1 == 0) { $rand1 = rand(); }
  0         0  
2250            
2251 100         277 my $rnorm = ($sd * CORE::sqrt(-2 * CORE::log($rand1))
2252             * CORE::sin(2 * $pi * $rand2))
2253             + $mean;
2254            
2255 100         198 push @x1_elements, $rnorm;
2256             }
2257            
2258 1         1033 return Rstats::Func::c_($r, @x1_elements);
2259             }
2260              
2261             sub round {
2262 7     7 0 11 my $r = shift;
2263            
2264 7 100       25 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2265 7         14 my ($_x1, $digits) = @_;
2266 7 100       21 $digits = $opt->{digits} unless defined $digits;
2267 7 100       19 $digits = 0 unless defined $digits;
2268            
2269 7         21 my $x1 = to_object($r, $_x1);
2270              
2271 7         20 my $ro = 10 ** $digits;
2272 7         10 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         883  
  7         178  
2273 7         435 my $x2 = Rstats::Func::c_($r, @x2_elements);
2274 7         70 Rstats::Func::copy_attrs_to($r, $x1, $x2);
2275 7         157 Rstats::Func::mode($r, $x2, 'double');
2276            
2277 7         123 return $x2;
2278             }
2279              
2280             sub rowMeans {
2281 1     1 0 3 my $r = shift;
2282            
2283 1         2 my $x1 = shift;
2284            
2285 1         15 my $dim_values = Rstats::Func::dim($r, $x1)->values;
2286 1 50       10 if (@$dim_values == 2) {
2287 1         2 my $x1_values = [];
2288 1         4 for my $col (1 .. $dim_values->[1]) {
2289 3         4 my $x1_value = 0;
2290 3         22 $x1_value += $x1->value($_, $col) for (1 .. $dim_values->[0]);
2291 3         10 push @$x1_values, $x1_value / $dim_values->[0];
2292             }
2293 1         47 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       9 if (@$dim_values == 2) {
2307 1         2 my $x1_values = [];
2308 1         5 for my $col (1 .. $dim_values->[1]) {
2309 3         5 my $x1_value = 0;
2310 3         20 $x1_value += $x1->value($_, $col) for (1 .. $dim_values->[0]);
2311 3         10 push @$x1_values, $x1_value;
2312             }
2313 1         33 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 8 my $r = shift;
2323            
2324 4 100       15 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2325            
2326 4         7 my ($_x1, $length) = @_;
2327 4         13 my $x1 = to_object($r, $_x1);
2328            
2329             # Replace
2330 4         8 my $replace = $opt->{replace};
2331            
2332 4         21 my $x1_length = Rstats::Func::get_length($r, $x1);
2333 4 50       11 $length = $x1_length unless defined $length;
2334            
2335 4 50 66     16 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         770 my $x1_elements = Rstats::Func::decompose($r, $x1);
2340 4         22 for my $i (0 .. $length - 1) {
2341 155         235 my $rand_num = int(rand @$x1_elements);
2342 155         250 my $rand_element = splice @$x1_elements, $rand_num, 1;
2343 155         211 push @x2_elements, $rand_element;
2344 155 100       374 push @$x1_elements, $rand_element if $replace;
2345             }
2346            
2347 4         787 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         4 my $x1 = to_object($r, $_x1);
2356 1         7 my $x1_values = $x1->values;
2357            
2358 1         3 my @x2_values;
2359 1         4 for my $x1_value (@$x1_values) {
2360 3         5 push @x2_values, @{seq($r, 1, $x1_value)->values};
  3         8  
2361             }
2362            
2363 1         69 return Rstats::Func::c_($r, @x2_values);
2364             }
2365              
2366              
2367             sub tail {
2368 3     3 0 6 my $r = shift;
2369            
2370 3         11 my ($x1, $x_n) = Rstats::Func::args_array($r, ['x1', 'n'], @_);
2371            
2372 3 100       15 my $n = defined $x_n ? $x_n->value : 6;
2373            
2374 3         57 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         6 my @e2;
2377 3         10 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         67 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 5 my $r = shift;
2389            
2390 2         3 my ($_x1) = @_;
2391            
2392 2         9 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         61 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         31 return $x2;
2402             }
2403              
2404             sub unique {
2405 79     79 0 145 my $r = shift;
2406            
2407 79         259 my $x1 = to_object($r, shift);
2408            
2409 79 100       785 if (Rstats::Func::is_vector($r, $x1)) {
2410 78         140 my $x2_elements = [];
2411 78         159 my $elements_count = {};
2412 78         99 my $na_count;
2413 78         107 for my $x1_element (@{Rstats::Func::decompose($r, $x1)}) {
  78         2084  
2414 486 100       6485 if (Rstats::Func::is_na($r, $x1_element)) {
2415 3 100       11 unless ($na_count) {
2416 2         5 push @$x2_elements, $x1_element;
2417             }
2418 3         20 $na_count++;
2419             }
2420             else {
2421 483         1048 my $str = Rstats::Func::to_string($r, $x1_element);
2422 483 100       1473 unless ($elements_count->{$str}) {
2423 392         751 push @$x2_elements, $x1_element;
2424             }
2425 483         2936 $elements_count->{$str}++;
2426             }
2427             }
2428              
2429 78         3275 return Rstats::Func::c_($r, @$x2_elements);
2430             }
2431             else {
2432 1         8 return $x1;
2433             }
2434             }
2435              
2436             sub median {
2437 2     2 0 6 my $r = shift;
2438            
2439 2         9 my $x1 = to_object($r, shift);
2440            
2441 2         6 my $x2 = unique($r, $x1);
2442 2         32 my $x3 = Rstats::Func::sort($r, $x2);
2443 2         35 my $x3_length = Rstats::Func::get_length($r, $x3);
2444            
2445 2 100       9 if ($x3_length % 2 == 0) {
2446 1         5 my $middle = $x3_length / 2;
2447 1         7 my $x4 = $x3->get($middle);
2448 1         9 my $x5 = $x3->get($middle + 1);
2449            
2450 1         6 return ($x4 + $x5) / 2;
2451             }
2452             else {
2453 1         6 my $middle = int($x3_length / 2) + 1;
2454 1         8 return $x3->get($middle);
2455             }
2456             }
2457              
2458             sub quantile {
2459 3     3 0 8 my $r = shift;
2460            
2461 3         12 my $x1 = to_object($r, shift);
2462            
2463 3         12 my $x2 = Rstats::Func::unique($r, $x1);
2464 3         322 my $x3 = Rstats::Func::sort($r, $x2);
2465 3         312 my $x3_length = Rstats::Func::get_length($r, $x3);
2466            
2467 3         8 my $quantile_elements = [];
2468            
2469             # Min
2470 3         22 push @$quantile_elements , $x3->get(1);
2471            
2472             # 1st quoter
2473 3 100       16 if ($x3_length % 4 == 0) {
2474 1         4 my $first_quoter = $x3_length * (1 / 4);
2475 1         7 my $x4 = $x3->get($first_quoter);
2476 1         8 my $x5 = $x3->get($first_quoter + 1);
2477            
2478 1         6 push @$quantile_elements, ((($x4 + $x5) / 2) + $x5) / 2;
2479             }
2480             else {
2481 2         8 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       33 if ($x3_length % 2 == 0) {
2487 1         3 my $middle = $x3_length / 2;
2488 1         10 my $x4 = $x3->get($middle);
2489 1         7 my $x5 = $x3->get($middle + 1);
2490            
2491 1         5 push @$quantile_elements, (($x4 + $x5) / 2);
2492             }
2493             else {
2494 2         8 my $middle = int($x3_length / 2) + 1;
2495 2         13 push @$quantile_elements, $x3->get($middle);
2496             }
2497            
2498             # 3rd quoter
2499 3 100       26 if ($x3_length % 4 == 0) {
2500 1         3 my $third_quoter = $x3_length * (3 / 4);
2501 1         8 my $x4 = $x3->get($third_quoter);
2502 1         9 my $x5 = $x3->get($third_quoter + 1);
2503            
2504 1         6 push @$quantile_elements, (($x4 + (($x4 + $x5) / 2)) / 2);
2505             }
2506             else {
2507 2         8 my $third_quoter = int($x3_length * (3 / 4)) + 1;
2508 2         11 push @$quantile_elements, $x3->get($third_quoter);
2509             }
2510            
2511             # Max
2512 3         39 push @$quantile_elements , $x3->get($x3_length);
2513            
2514 3         81 my $x4 = Rstats::Func::c_($r, @$quantile_elements);
2515 3         185 Rstats::Func::names($r, $x4, Rstats::Func::c_($r, qw/0% 25% 50% 75% 100%/));
2516            
2517 3         132 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 2 my $r = shift;
2532            
2533 1         5 my $x1 = to_object($r, shift);
2534            
2535 1         4 my $var = sum($r, ($x1 - Rstats::Func::mean($r, $x1)) ** 2) / (Rstats::Func::get_length($r, $x1) - 1);
2536            
2537 1         31 return $var;
2538             }
2539              
2540             sub which {
2541 1     1 0 3 my $r = shift;
2542            
2543 1         2 my ($_x1, $cond_cb) = @_;
2544            
2545 1         5 my $x1 = to_object($r, $_x1);
2546 1         6 my $x1_values = $x1->values;
2547 1         3 my @x2_values;
2548 1         5 for (my $i = 0; $i < @$x1_values; $i++) {
2549 3         13 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 4 my $r = shift;
2560            
2561 4         9 my ($x1, $x2) = @_;
2562            
2563 4 100 100     51 if (Rstats::Func::is_null($r, $x1) || Rstats::Func::is_null($r, $x2)) {
2564 2         205 Carp::croak "requires numeric/complex matrix/vector arguments";
2565             }
2566            
2567             # Convert to matrix
2568 2 50       29 $x1 = Rstats::Func::t($r, Rstats::Func::as_matrix($r, $x1))
2569             if Rstats::Func::is_vector($r, $x1);
2570 2 50       32 $x2 = Rstats::Func::as_matrix($r, $x2) if Rstats::Func::is_vector($r, $x2);
2571            
2572             # Calculate
2573 2 50 33     36 if (Rstats::Func::is_matrix($r, $x1) && Rstats::Func::is_matrix($r, $x2)) {
2574            
2575 2 50 33     23 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       26 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         20 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         6 for (my $col = 1; $col <= $col_max; $col++) {
2585 1         4 for (my $row = 1; $row <= $row_max; $row++) {
2586 1         5 my $x1_part = Rstats::Func::get($r, $x1, $row);
2587 1         13 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         14 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         18 my $ncol = Rstats::Func::ncol($r, $x1)->value;
2609            
2610 1         26 my @values = (1 .. $nrow) x $ncol;
2611            
2612 1         246 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 9 my $r = shift;
2619            
2620 5         12 my $x1 = shift;
2621            
2622 5 100       51 if (Rstats::Func::is_data_frame($r, $x1)) {
    100          
2623 1         32 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         39 return Rstats::Func::c_($r, Rstats::Func::dim($r, $x1)->values->[1]);
2630             }
2631             }
2632              
2633             sub seq {
2634 139     139 0 232 my $r = shift;
2635            
2636             # Option
2637 139 100       468 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2638            
2639             # Along
2640 139         293 my $_along = $opt->{along};
2641 139 100       326 if (defined $_along) {
2642 1         5 my $along = to_object($r, $_along);
2643 1         6 my $length = Rstats::Func::get_length($r, $along);
2644 1         7 return seq($r, 1, $length);
2645             }
2646             else {
2647 138         251 my ($from, $to) = @_;
2648            
2649             # From
2650 138 100       409 $from = $opt->{from} unless defined $from;
2651 138 50       318 Carp::croak "seq function need from option" unless defined $from;
2652            
2653             # To
2654 138 100       361 $to = $opt->{to} unless defined $to;
2655 138 50       292 Carp::croak "seq function need to option" unless defined $to;
2656              
2657             # Length
2658 138         232 my $length = $opt->{length};
2659            
2660             # By
2661 138         222 my $by = $opt->{by};
2662            
2663 138 50 66     399 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       321 unless (defined $by) {
2668 135 100       415 if ($to >= $from) {
2669 134         214 $by = 1;
2670             }
2671             else {
2672 1         3 $by = -1;
2673             }
2674             }
2675 138 50       334 Carp::croak "by option should be except for 0" if $by == 0;
2676            
2677 138 50       289 $to = $from unless defined $to;
2678            
2679 138 100 66     393 if (defined $length && $from ne $to) {
2680 1         4 $by = ($to - $from) / ($length - 1);
2681             }
2682            
2683 138         259 my $elements = [];
2684 138 100       422 if ($to == $from) {
    100          
2685 2         5 $elements->[0] = $to;
2686             }
2687             elsif ($to > $from) {
2688 134 50       299 if ($by < 0) {
2689 0         0 Carp::croak "by option is invalid number(seq function)";
2690             }
2691            
2692 134         204 my $element = $from;
2693 134         351 while ($element <= $to) {
2694 2422         3484 push @$elements, $element;
2695 2422         4850 $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         4 my $element = $from;
2704 2         6 while ($element >= $to) {
2705 8         16 push @$elements, $element;
2706 8         19 $element += $by;
2707             }
2708             }
2709            
2710 138         18165 return Rstats::Func::c_($r, @$elements);
2711             }
2712             }
2713              
2714             sub numeric {
2715 1     1 0 3 my $r = shift;
2716            
2717 1         3 my $num = shift;
2718            
2719 1         36 return Rstats::Func::c_($r, (0) x $num);
2720             }
2721              
2722             sub _fix_pos {
2723 1137     1137   1735 my $r = shift;
2724            
2725 1137         2038 my ($data1, $datx2, $reverse) = @_;
2726            
2727 1137         1328 my $x1;
2728             my $x2;
2729 1137 100       2340 if (ref $datx2) {
2730 904         1020 $x1 = $data1;
2731 904         1219 $x2 = $datx2;
2732             }
2733             else {
2734 233 100       472 if ($reverse) {
2735 212         3790 $x1 = Rstats::Func::c_($r, $datx2);
2736 212         1194 $x2 = $data1;
2737             }
2738             else {
2739 21         35 $x1 = $data1;
2740 21         366 $x2 = Rstats::Func::c_($r, $datx2);
2741             }
2742             }
2743            
2744 1137         36162 return ($x1, $x2);
2745             }
2746              
2747             sub bool {
2748 32978     32978 0 43311 my $r = shift;
2749            
2750 32978         40658 my $x1 = shift;
2751            
2752 32978         140580 my $length = Rstats::Func::get_length($r, $x1);
2753 32978 100       98412 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         192 Carp::carp 'In if (a) { : the condition has length > 1 and only the first element will be used';
2758             }
2759            
2760 32977         163987 my $type = $x1->get_type;
2761 32977         162016 my $value = $x1->value;
2762              
2763 32977         49667 my $is;
2764 32977 50 33     253907 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     33 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         44251 $is = $value;
2780             }
2781             else {
2782 0         0 Carp::croak "Invalid type";
2783             }
2784            
2785 32977 50       63596 if (!defined $value) {
2786 0         0 Carp::croak "Error in bool context (a) { : missing value where TRUE/FALSE needed"
2787             }
2788              
2789 32977         183919 return $is;
2790             }
2791              
2792             sub set {
2793 58     58 0 102 my ($r, $x1) = @_;
2794            
2795 58 100 100     401 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         14 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 1468 my $r = shift;
2813            
2814 998         1303 my $x1 = shift;
2815            
2816 998 100       2412 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
2817 998         1379 my $dim_drop;
2818             my $level_drop;
2819 998 100       35197 if (Rstats::Func::is_factor($r, $x1)) {
2820 12         29 $level_drop = $opt->{drop};
2821             }
2822             else {
2823 986         1700 $dim_drop = $opt->{drop};
2824             }
2825            
2826 998 100       13737 $dim_drop = 1 unless defined $dim_drop;
2827 998 100       2134 $level_drop = 0 unless defined $level_drop;
2828            
2829 998         2311 my @_indexs = @_;
2830              
2831 998         1148 my $_indexs;
2832 998 50       2065 if (@_indexs) {
2833 998         1583 $_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         5437 $x1->at($_indexs);
2840            
2841 998         1399 my ($poss, $x2_dim, $new_indexes) = @{Rstats::Util::parse_index($r, $x1, $dim_drop, $_indexs)};
  998         3000  
2842            
2843 998         5925 my $x1_values = $x1->values;
2844 998         2142 my @x2_values = map { $x1_values->[$_] } @$poss;
  1146         3078  
2845            
2846             # array
2847 998         1389 my $x_matrix;
2848 998 100       5157 if ($x1->get_type eq "character") {
    50          
    100          
    50          
    0          
2849 24         194 $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         13205 $x_matrix = c_double($r, \@x2_values);
2856             }
2857             elsif ($x1->get_type eq "integer") {
2858 12         98 $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         59842 my $x2 = Rstats::Func::array(
2868             $r,
2869             $x_matrix,
2870             Rstats::Func::c_($r, @$x2_dim)
2871             );
2872            
2873             # Copy attributes
2874 998         18955 Rstats::Func::copy_attrs_to($r, $x1, $x2, {new_indexes => $new_indexes, exclude => ['dim']});
2875              
2876             # level drop
2877 998 100       3686 if ($level_drop) {
2878 1         63 my $p = Rstats::Func::as_character($r, $x2);
2879 1         73 $x2 = Rstats::Func::factor($r, Rstats::Func::as_character($r, $x2));
2880             }
2881            
2882 998         21506 return $x2;
2883             }
2884              
2885 0     0 0 0 sub getin_array { get(@_) }
2886              
2887             sub to_string_array {
2888 560     560 0 798 my $r = shift;
2889            
2890 560         749 my $x1 = shift;
2891            
2892 560         10427 my $is_factor = Rstats::Func::is_factor($r, $x1);
2893 560         12371 my $is_ordered = Rstats::Func::is_ordered($r, $x1);
2894 560         3332 my $levels;
2895 560 100       1776 if ($is_factor) {
2896 4         53 $levels = Rstats::Func::levels($r, $x1)->values;
2897             }
2898            
2899 560 100       11009 $x1 = Rstats::Func::as_character($r, $x1) if Rstats::Func::is_factor($r, $x1);
2900            
2901 560         7560 my $is_character = Rstats::Func::is_character($r, $x1);
2902              
2903 560         2925 my $values = $x1->values;
2904 560         2838 my $type = $x1->get_type;
2905            
2906 560         2925 my $dim_values = $x1->dim_as_array->values;
2907            
2908 560         2911 my $dim_length = @$dim_values;
2909 560         913 my $dim_num = $dim_length - 1;
2910 560         1023 my $poss = [];
2911            
2912 560         792 my $str;
2913 560 50       1141 if (@$values) {
2914 560 100       1163 if ($dim_length == 1) {
    100          
2915 550         4835 my $names = Rstats::Func::names($r, $x1)->values;
2916 550 100       2054 if (@$names) {
2917 1         6 $str .= join(' ', @$names) . "\n";
2918             }
2919 550         1018 my @parts = map { Rstats::Func::_value_to_string($r, $x1, $_, $type, $is_factor) } @$values;
  618         1358  
2920 550         1863 $str .= '[1] ' . join(' ', @parts) . "\n";
2921             }
2922             elsif ($dim_length == 2) {
2923 7         15 $str .= ' ';
2924            
2925 7         20 my $colnames = Rstats::Func::colnames($r, $x1)->values;
2926 7 100       33 if (@$colnames) {
2927 1         5 $str .= join(' ', @$colnames) . "\n";
2928             }
2929             else {
2930 6         23 for my $d2 (1 .. $dim_values->[1]) {
2931 12 100       45 $str .= $d2 == $dim_values->[1] ? "[,$d2]\n" : "[,$d2] ";
2932             }
2933             }
2934            
2935 7         23 my $rownames = Rstats::Func::rownames($r, $x1)->values;
2936 7 100       30 my $use_rownames = @$rownames ? 1 : 0;
2937 7         28 for my $d1 (1 .. $dim_values->[0]) {
2938 46 100       73 if ($use_rownames) {
2939 2         4 my $rowname = $rownames->[$d1 - 1];
2940 2         6 $str .= "$rowname ";
2941             }
2942             else {
2943 44         86 $str .= "[$d1,] ";
2944             }
2945            
2946 46         54 my @parts;
2947 46         106 for my $d2 (1 .. $dim_values->[1]) {
2948 74         360 my $part = $x1->value($d1, $d2);
2949 74         195 push @parts, Rstats::Func::_value_to_string($r, $x1, $part, $type, $is_factor);
2950             }
2951            
2952 46         154 $str .= join(' ', @parts) . "\n";
2953             }
2954             }
2955             else {
2956 3         6 my $code;
2957             $code = sub {
2958 5     5   12 my (@dim_values) = @_;
2959 5         9 my $dim_value = pop @dim_values;
2960            
2961 5         20 for (my $i = 1; $i <= $dim_value; $i++) {
2962 12         47 $str .= (',' x $dim_num) . "$i" . "\n";
2963 12         27 unshift @$poss, $i;
2964 12 100       29 if (@dim_values > 2) {
2965 2         5 $dim_num--;
2966 2         10 $code->(@dim_values);
2967 2         5 $dim_num++;
2968             }
2969             else {
2970 10         20 $str .= ' ';
2971            
2972 10         37 my $l_dimnames = Rstats::Func::dimnames($r, $x1);
2973 10         17 my $dimnames;
2974 10 50       97 if (Rstats::Func::is_null($r, $l_dimnames)) {
2975 10         21 $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       50 if (@$dimnames) {
2983 0         0 $str .= join(' ', @$dimnames) . "\n";
2984             }
2985             else {
2986 10         32 for my $d2 (1 .. $dim_values[1]) {
2987 36 100       117 $str .= $d2 == $dim_values[1] ? "[,$d2]\n" : "[,$d2] ";
2988             }
2989             }
2990              
2991 10         26 for my $d1 (1 .. $dim_values[0]) {
2992 46         99 $str .= "[$d1,] ";
2993            
2994 46         70 my @parts;
2995 46         96 for my $d2 (1 .. $dim_values[1]) {
2996 168         864 my $part = $x1->value($d1, $d2, @$poss);
2997 168         499 push @parts, Rstats::Func::_value_to_string($r, $x1, $part, $type, $is_factor);
2998             }
2999            
3000 46         223 $str .= join(' ', @parts) . "\n";
3001             }
3002             }
3003 12         61 shift @$poss;
3004             }
3005 3         31 };
3006 3         10 $code->(@$dim_values);
3007             }
3008              
3009 560 100       1693 if ($is_factor) {
3010 4 100       13 if ($is_ordered) {
3011 1         5 $str .= 'Levels: ' . join(' < ', @$levels) . "\n";
3012             }
3013             else {
3014 3         19 $str .= 'Levels: ' . join(' ', , @$levels) . "\n";
3015             }
3016             }
3017             }
3018             else {
3019 0         0 $str = 'NULL';
3020             }
3021            
3022 560         5554 return $str;
3023             }
3024              
3025             sub _value_to_string {
3026 908     908   1313 my $r = shift;
3027            
3028 908         1695 my ($x1, $value, $type, $is_factor) = @_;
3029            
3030 908         1117 my $string;
3031 908 100       2680 if ($is_factor) {
3032 24 100       45 if (!defined $value) {
3033 2         4 $string = '';
3034             }
3035             else {
3036 22         59 $string = "$value";
3037             }
3038             }
3039             else {
3040 884 100       3356 if (!defined $value) {
    100          
    100          
    100          
3041 1         3 $string = 'NA';
3042             }
3043             elsif ($type eq 'complex') {
3044 5   50     17 my $re = $value->{re} || 0;
3045 5   100     24 my $im = $value->{im} || 0;
3046 5         33 $string = "$re";
3047 5 100       17 $string .= $im >= 0 ? "+$im" : $im;
3048 5         10 $string .= 'i';
3049             }
3050             elsif ($type eq 'character') {
3051 291         681 $string = '"' . $value . '"';
3052             }
3053             elsif ($type eq 'logical') {
3054 9 100       27 $string = $value ? 'TRUE' : 'FALSE';
3055             }
3056             else {
3057 578         2402 $string = "$value";
3058             }
3059             }
3060            
3061 908         3410 return $string;
3062             }
3063              
3064             sub str {
3065 11     11 0 21 my $r = shift;
3066            
3067 11         15 my $x1 = shift;
3068            
3069 11         20 my @str;
3070            
3071 11 50 66     106 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         19 my $short_type;
3078 11 100       52 if ($type eq 'character') {
    100          
    100          
    100          
    50          
3079 1         3 $short_type = 'chr';
3080             }
3081             elsif ($type eq 'complex') {
3082 1         2 $short_type = 'cplx';
3083             }
3084             elsif ($type eq 'double') {
3085 7         12 $short_type = 'num';
3086             }
3087             elsif ($type eq 'integer') {
3088 1         3 $short_type = 'int';
3089             }
3090             elsif ($type eq 'logical') {
3091 1         3 $short_type = 'logi';
3092             }
3093             else {
3094 0         0 $short_type = 'Unkonown';
3095             }
3096 11         21 push @str, $short_type;
3097            
3098             # Dimention
3099 11         39 my @dim_str;
3100 11         51 my $length = Rstats::Func::get_length($r, $x1);
3101 11 100       26 if (exists $x1->{dim}) {
3102 3         17 my $dim_values = $x1->{dim}->values;
3103 3         24 for (my $i = 0; $i < $x1->{dim}->get_length; $i++) {
3104 4         7 my $d = $dim_values->[$i];
3105 4         7 my $d_str;
3106 4 100       12 if ($d == 1) {
3107 1         3 $d_str = "1";
3108             }
3109             else {
3110 3         7 $d_str = "1:$d";
3111             }
3112            
3113 4 100       22 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       24 if ($length != 1) {
3121 7         18 push @dim_str, "1:$length";
3122             }
3123             }
3124 11 100       31 if (@dim_str) {
3125 10         22 my $dim_str = join(', ', @dim_str);
3126 10         25 push @str, "[$dim_str]";
3127             }
3128            
3129             # Vector
3130 11         16 my @element_str;
3131 11 100       27 my $max_count = $length > 10 ? 10 : $length;
3132 11         79 my $is_character = is_character($r, $x1);
3133 11         55 my $values = $x1->values;
3134 11         36 for (my $i = 0; $i < $max_count; $i++) {
3135 48         108 push @element_str, Rstats::Func::_value_to_string($r, $x1, $values->[$i], $type);
3136             }
3137 11 100       25 if ($length > 10) {
3138 2         5 push @element_str, '...';
3139             }
3140 11         23 my $element_str = join(' ', @element_str);
3141 11         105 push @str, $element_str;
3142             }
3143            
3144 11         78 my $str = join(' ', @str);
3145            
3146 11         62 return $str;
3147             }
3148              
3149             sub at {
3150 1370     1370 0 1968 my $r = shift;
3151            
3152 1370         1881 my $x1 = shift;
3153            
3154 1370 100       3144 if (@_) {
3155 1312         3522 $x1->{at} = [@_];
3156            
3157 1312         3651 return $x1;
3158             }
3159            
3160 58         151 return $x1->{at};
3161             }
3162              
3163             sub _name_to_index {
3164 31     31   53 my $r = shift;
3165 31         49 my $x1 = shift;
3166 31         124 my $x1_index = Rstats::Func::to_object($r, shift);
3167            
3168 31         191 my $e1_name = $x1_index->value;
3169 31         60 my $found;
3170 31         430 my $names = Rstats::Func::names($r, $x1)->values;
3171 31         171 my $index;
3172 31         110 for (my $i = 0; $i < @$names; $i++) {
3173 55         103 my $name = $names->[$i];
3174 55 100       167 if ($e1_name eq $name) {
3175 31         50 $index = $i + 1;
3176 31         40 $found = 1;
3177 31         66 last;
3178             }
3179             }
3180 31 50       78 croak "Not found $e1_name" unless $found;
3181            
3182 31         109 return $index;
3183             }
3184              
3185             sub nlevels {
3186 2     2 0 4 my $r = shift;
3187            
3188 2         4 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 457 my ($r, $x1, $_index) = @_;
3195            
3196 256 50       581 unless (defined $_index) {
3197 0         0 $_index = $x1->at;
3198             }
3199 256         1372 $x1->at($_index);
3200            
3201 256         2109 my $x1_index = Rstats::Func::to_object($r, $_index);
3202 256         404 my $index;
3203 256 100       2370 if (Rstats::Func::is_character($r, $x1_index)) {
3204 25         77 $index = Rstats::Func::_name_to_index($r, $x1, $x1_index);
3205             }
3206             else {
3207 231         1224 $index = $x1_index->values->[0];
3208             }
3209 256         7068 my $elements = $x1->list;
3210 256         1798 my $element = $elements->[$index - 1];
3211            
3212 256         2246 return $element;
3213             }
3214              
3215             sub get_list {
3216 3     3 0 4 my $r = shift;
3217 3         4 my $x1 = shift;
3218 3         14 my $x_index = Rstats::Func::to_object($r, shift);
3219            
3220 3         111 my $elements = $x1->list;
3221            
3222 3         19 my $class = ref $x1;
3223 3         13 my $list = Rstats::Func::list($r);;
3224 3         61 my $list_elements = $list->list;
3225            
3226 3         18 my $index_values;
3227 3 100       28 if (Rstats::Func::is_character($r, $x_index)) {
3228 1         3 $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         36 $index_values = $x_index->values;
3235             }
3236 3         14 for my $i (@{$index_values}) {
  3         8  
3237 5         13 push @$list_elements, $elements->[$i - 1];
3238             }
3239            
3240             Rstats::Func::copy_attrs_to(
3241 3         110 $r, $x1, $list, {new_indexes => [Rstats::Func::c_($r, @$index_values)]}
3242             );
3243              
3244 3         49 return $list;
3245             }
3246              
3247             sub set_list {
3248 8     8 0 42 my $r = shift;
3249 8         18 my ($x1, $v1) = @_;
3250            
3251 8         37 my $_index = $x1->at;
3252 8         60 my $x1_index = Rstats::Func::to_object($r, @$_index);
3253 8         13 my $index;
3254 8 100       64 if (Rstats::Func::is_character($r, $x1_index)) {
3255 1         4 $index = Rstats::Func::_name_to_index($r, $x1, $x1_index);
3256             }
3257             else {
3258 7         38 $index = $x1_index->values->[0];
3259             }
3260 8         68 $v1 = Rstats::Func::to_object($r, $v1);
3261            
3262 8 100       68 if (Rstats::Func::is_null($r, $v1)) {
3263 3         6 splice @{$x1->list}, $index - 1, 1;
  3         65  
3264 3 100       38 if (exists $x1->{names}) {
3265 2         13 my $new_names_values = $x1->{names}->values;
3266 2         6 splice @$new_names_values, $index - 1, 1;
3267 2         30 $x1->{names} = Rstats::Func::c_character($r, @$new_names_values);
3268             }
3269            
3270 3 100       26 if (exists $x1->{dimnames}) {
3271 2         19 my $new_dimname_values = $x1->{dimnames}[1]->values;
3272 2         7 splice @$new_dimname_values, $index - 1, 1;
3273 2         24 $x1->{dimnames}[1] = Rstats::Func::c_character($r, @$new_dimname_values);
3274             }
3275             }
3276             else {
3277 5 100       43 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       5 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         133 $x1->list->[$index - 1] = $v1;
3286             }
3287            
3288 8         104 return $x1;
3289             }
3290              
3291             sub to_string_list {
3292 3     3 0 6 my $r = shift;
3293 3         5 my $x1 = shift;
3294            
3295 3         6 my $poses = [];
3296 3         4 my $str = '';
3297 3         9 _to_string_list($r, $x1, $poses, \$str);
3298            
3299 3         22 return $str;
3300             }
3301              
3302             sub _to_string_list {
3303 4     4   6 my ($r, $list, $poses, $str_ref) = @_;
3304            
3305 4         91 my $elements = $list->list;
3306 4         57 for (my $i = 0; $i < @$elements; $i++) {
3307 8         16 push @$poses, $i + 1;
3308 8         15 $$str_ref .= join('', map { "[[$_]]" } @$poses) . "\n";
  10         37  
3309            
3310 8         14 my $element = $elements->[$i];
3311 8 100       18 if ($element->{object_type} eq 'list') {
3312 1         5 _to_string_list($r, $element, $poses, $str_ref);
3313             }
3314             else {
3315 7         26 $$str_ref .= Rstats::Func::to_string($r, $element) . "\n";
3316             }
3317 8         33 pop @$poses;
3318             }
3319             }
3320              
3321 2     2 0 6 sub set_dataframe { Rstats::Func::set_list(@_) }
3322              
3323 115     115 0 268 sub getin_dataframe { Rstats::Func::getin_list(@_) }
3324              
3325             sub get_dataframe {
3326 16     16 0 27 my $r = shift;
3327            
3328 16         25 my $x1 = shift;
3329 16         34 my $_row_index = shift;
3330 16         28 my $_col_index = shift;
3331            
3332             # Fix column index and row index
3333 16 100       57 unless (defined $_col_index) {
3334 3         5 $_col_index = $_row_index;
3335 3         19 $_row_index = Rstats::Func::NULL($r);
3336             }
3337 16         52 my $row_index = Rstats::Func::to_object($r, $_row_index);
3338 16         60 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       168 if (Rstats::Func::is_null($r, $col_index)) {
    100          
    100          
3343 7         108 $col_index_values = [1 .. Rstats::Func::names($r, $x1)->get_length];
3344             }
3345             elsif (Rstats::Func::is_character($r, $col_index)) {
3346 2         7 $col_index_values = [];
3347 2         5 for my $col_index_value (@{$col_index->values}) {
  2         13  
3348 3         10 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         11 my $tmp_col_index_values = $col_index->values;
3353 2         8 for (my $i = 0; $i < @$tmp_col_index_values; $i++) {
3354 6 100       27 push @$col_index_values, $i + 1 if $tmp_col_index_values->[$i];
3355             }
3356             }
3357             else {
3358 5         25 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       7 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         2 $col_index_values = [];
3368 1         16 for (my $index = 1; $index <= Rstats::Func::names($r, $x1)->get_length; $index++) {
3369 3 100       52 push @$col_index_values, $index unless $delete_col_index_values_h->{$index};
3370             }
3371             }
3372             else {
3373 4         8 $col_index_values = $col_index_values_tmp;
3374             }
3375             }
3376            
3377             # Extract columns
3378 16         490 my $elements = $x1->list;
3379 16         108 my $new_elements = [];
3380 16         31 for my $i (@{$col_index_values}) {
  16         46  
3381 35         89 push @$new_elements, $elements->[$i - 1];
3382             }
3383            
3384             # Extract rows
3385 16         37 for my $new_element (@$new_elements) {
3386 35 100       333 $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         91 my $data_frame = Rstats::Func::new_data_frame($r);;
3392 16         419 $data_frame->list($new_elements);
3393 16         1652 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         267 $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         154 return $data_frame;
3404             }
3405              
3406             sub to_string_dataframe {
3407 1     1 0 3 my $r = shift;
3408            
3409 1         3 my $x1 = shift;
3410              
3411 1         14 my $t = Text::UnicodeTable::Simple->new(border => 0, alignment => 'right');
3412            
3413             # Names
3414 1         56 my $column_names = Rstats::Func::names($r, $x1)->values;
3415 1         12 $t->set_header('', @$column_names);
3416            
3417             # columns
3418 1         174 my $columns = [];
3419 1         6 for (my $i = 1; $i <= @$column_names; $i++) {
3420 2         15 my $x = $x1->getin($i);
3421 2 100       48 $x = Rstats::Func::as_character($r, $x) if Rstats::Func::is_factor($r, $x);
3422 2         45 push @$columns, $x->values;
3423             }
3424 1         4 my $col_count = @{$columns};
  1         3  
3425 1         2 my $row_count = @{$columns->[0]};
  1         4  
3426            
3427 1         6 for (my $i = 0; $i < $row_count; $i++) {
3428 3         298 my @row;
3429 3         7 push @row, $i + 1;
3430 3         10 for (my $k = 0; $k < $col_count; $k++) {
3431 6         23 push @row, $columns->[$k][$i];
3432             }
3433 3         13 $t->add_row(@row);
3434             }
3435            
3436 1         128 return "$t";
3437             }
3438              
3439             sub sweep {
3440 9     9 0 12 my $r = shift;
3441            
3442 9         39 my ($x1, $x_margin, $x2, $x_func)
3443             = Rstats::Func::args_array($r, ['x1', 'margin', 'x2', 'FUN'], @_);
3444            
3445 9         56 my $x_margin_values = $x_margin->values;
3446 9 100       47 my $func = defined $x_func ? $x_func->value : '-';
3447            
3448 9         85 my $x2_dim_values = Rstats::Func::dim($r, $x2)->values;
3449 9         117 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         18 my $x_result_elements = [];
3454 9         25 for (my $x1_pos = 0; $x1_pos < $x1_length; $x1_pos++) {
3455 54         215 my $x1_index = Rstats::Util::pos_to_index($x1_pos, $x1_dim_values);
3456            
3457 54         83 my $new_index = [];
3458 54         107 for my $x_margin_value (@$x_margin_values) {
3459 60         134 push @$new_index, $x1_index->[$x_margin_value - 1];
3460             }
3461            
3462 54         62 my $e1 = $x2->value(@{$new_index});
  54         280  
3463 54         224 push @$x_result_elements, $e1;
3464             }
3465 9         607 my $x3 = Rstats::Func::c_($r, @$x_result_elements);
3466            
3467 9         111 my $x4;
3468 9 100       47 if ($func eq '+') {
    100          
    100          
    100          
    100          
    50          
3469 1         10 $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         6 $x4 = $x1 / $x3;
3479             }
3480             elsif ($func eq '**') {
3481 1         5 $x4 = $x1 ** $x3;
3482             }
3483             elsif ($func eq '%') {
3484 1         5 $x4 = $x1 % $x3;
3485             }
3486            
3487 9         50 Rstats::Func::copy_attrs_to($r, $x1, $x4);
3488            
3489 9         101 return $x4;
3490             }
3491              
3492             sub set_seed {
3493 2     2 0 4 my ($r, $seed) = @_;
3494            
3495 2         7 $r->{seed} = $seed;
3496             }
3497              
3498             sub runif {
3499 6     6 0 10 my $r = shift;
3500              
3501 6         22 my ($x_count, $x_min, $x_max)
3502             = Rstats::Func::args_array($r, ['count', 'min', 'max'], @_);
3503            
3504 6         42 my $count = $x_count->value;
3505 6 100       23 my $min = defined $x_min ? $x_min->value : 0;
3506 6 100       23 my $max = defined $x_max ? $x_max->value : 1;
3507 6 50       16 Carp::croak "runif third argument must be bigger than second argument"
3508             if $min > $max;
3509            
3510 6         7 my $diff = $max - $min;
3511 6         7 my @x1_elements;
3512 6 100       18 if (defined $r->{seed}) {
3513 2         4 srand $r->{seed};
3514             }
3515            
3516 6         16 for (1 .. $count) {
3517 220         296 my $rand = rand($diff) + $min;
3518 220         339 push @x1_elements, $rand;
3519             }
3520            
3521 6         11 $r->{seed} = undef;
3522            
3523 6         2178 return Rstats::Func::c_($r, @x1_elements);
3524             }
3525              
3526             sub apply {
3527 10     10 0 24 my $r = shift;
3528            
3529 10         31 my $func_name = splice(@_, 2, 1);
3530 10 100       215 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3531              
3532 10         102 my ($x1, $x_margin)
3533             = Rstats::Func::args_array($r, ['x1', 'margin'], @_);
3534              
3535 10         159 my $dim_values = Rstats::Func::dim($r, $x1)->values;
3536 10         87 my $margin_values = $x_margin->values;
3537 10         22 my $new_dim_values = [];
3538 10         26 for my $i (@$margin_values) {
3539 14         40 push @$new_dim_values, $dim_values->[$i - 1];
3540             }
3541            
3542 10         43 my $x1_length = Rstats::Func::get_length($r, $x1);
3543 10         19 my $new_elements_array = [];
3544 10         30 for (my $i = 0; $i < $x1_length; $i++) {
3545 186         891 my $index = Rstats::Util::pos_to_index($i, $dim_values);
3546 186         1055 my $e1 = $x1->value(@$index);
3547 186         353 my $new_index = [];
3548 186         387 for my $i (@$margin_values) {
3549 264         620 push @$new_index, $index->[$i - 1];
3550             }
3551 186         494 my $new_pos = Rstats::Util::index_to_pos($new_index, $new_dim_values);
3552 186   100     561 $new_elements_array->[$new_pos] ||= [];
3553 186         231 push @{$new_elements_array->[$new_pos]}, $e1;
  186         832  
3554             }
3555            
3556 10         19 my $new_elements = [];
3557 10         22 for my $element_array (@$new_elements_array) {
3558 48         2917 push @$new_elements, $func->($r, Rstats::Func::c_($r, @$element_array));
3559             }
3560              
3561 10         249 my $x2 = Rstats::Func::c_($r, @$new_elements);
3562 10         118 Rstats::Func::copy_attrs_to($r, $x1, $x2);
3563 10         146 $x2->{dim} = Rstats::Func::c_integer($r, @$new_dim_values);
3564            
3565 10 100       96 if ($x2->{dim}->get_length == 1) {
3566 6         35 delete $x2->{dim};
3567             }
3568            
3569 10         206 return $x2;
3570              
3571             }
3572            
3573             sub mapply {
3574 3     3 0 6 my $r = shift;
3575            
3576 3         9 my $func_name = splice(@_, 0, 1);
3577 3 50       66 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3578              
3579 3         23 my @xs = @_;
3580 3         4 @xs = map { Rstats::Func::c_($r, $_) } @xs;
  6         89  
3581            
3582             # Fix length
3583 3         5 my @xs_length = map { Rstats::Func::get_length($r, $_) } @xs;
  6         26  
3584 3         10 my $max_length = List::Util::max @xs_length;
3585 3         14 for my $x (@xs) {
3586 6 100       34 if (Rstats::Func::get_length($r, $x) < $max_length) {
3587 1         81 $x = Rstats::Func::array($r, $x, $max_length);
3588             }
3589             }
3590            
3591             # Apply
3592 3         6 my $new_xs = [];
3593 3         8 for (my $i = 0; $i < $max_length; $i++) {
3594 10         20 my @args = map { $_->value($i + 1) } @xs;
  20         104  
3595 10         24 my $x = $func->($r, @args);
3596 10         38 push @$new_xs, $x;
3597             }
3598            
3599 3 100       8 if (@$new_xs == 1) {
3600 1         10 return $new_xs->[0];
3601             }
3602             else {
3603 2         7 return Rstats::Func::list($r, @$new_xs);
3604             }
3605             }
3606            
3607             sub tapply {
3608 1     1 0 4 my $r = shift;
3609            
3610 1         3 my $func_name = splice(@_, 2, 1);
3611 1 50       24 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3612              
3613 1         9 my ($x1, $x2)
3614             = Rstats::Func::args_array($r, ['x1', 'x2'], @_);
3615            
3616 1         3 my $new_values = [];
3617 1         6 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         6 my $index = $x2_values->[$i];
3624 5   100     17 $new_values->[$index] ||= [];
3625 5         5 push @{$new_values->[$index]}, $x1_value;
  5         29  
3626             }
3627            
3628             # Apply
3629 1         3 my $new_values2 = [];
3630 1         4 for (my $i = 1; $i < @$new_values; $i++) {
3631 2         4 my $x = $func->($r, Rstats::Func::c_($r, @{$new_values->[$i]}));
  2         77  
3632 2         21 push @$new_values2, $x;
3633             }
3634            
3635 1         2 my $x4_length = @$new_values2;
3636 1         70 my $x4 = Rstats::Func::array($r, Rstats::Func::c_($r, @$new_values2), $x4_length);
3637 1         37 Rstats::Func::names($r, $x4, Rstats::Func::levels($r, $x2));
3638            
3639 1         15 return $x4;
3640             }
3641              
3642             sub lapply {
3643 2     2 0 4 my $r = shift;
3644            
3645 2         6 my $func_name = splice(@_, 1, 1);
3646 2 50       58 my $func = ref $func_name ? $func_name : $r->helpers->{$func_name};
3647              
3648 2         21 my ($x1) = Rstats::Func::args_array($r, ['x1'], @_);
3649            
3650 2         5 my $new_elements = [];
3651 2         3 for my $element (@{$x1->list}) {
  2         44  
3652 4         60 push @$new_elements, $func->($r, $element);
3653             }
3654            
3655 2         7 my $x2 = Rstats::Func::list($r, @$new_elements);
3656 2         19 Rstats::Func::copy_attrs_to($r, $x1, $x2);
3657            
3658 2         7 return $x2;
3659             }
3660            
3661             sub sapply {
3662 1     1 0 3 my $r = shift;
3663 1         10 my $x1 = $r->lapply(@_);
3664            
3665 1         3 my $x2 = Rstats::Func::c_($r, @{$x1->list});
  1         22  
3666            
3667 1         29 return $x2;
3668             }
3669              
3670             sub to_string {
3671 565     565 0 949 my ($r, $x1) = @_;
3672            
3673 565 100 66     2445 if ($x1->{object_type} eq 'NULL') {
    100          
    100          
    50          
3674 1         6 return "NULL";
3675             }
3676             elsif ($x1->{object_type} eq 'array' || $x1->{object_type} eq 'factor') {
3677 560         1222 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         7 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 1574 my ($r, $x1) = @_;
3693            
3694 1017 100 66     3361 if ($x1->{object_type} eq 'array' || $x1->{object_type} eq 'factor') {
    100          
    50          
3695 998         2309 return Rstats::Func::get_array(@_);
3696             }
3697             elsif ($x1->{object_type} eq 'list') {
3698 3         21 return Rstats::Func::get_list(@_);
3699             }
3700             elsif ($x1->{object_type} eq 'data.frame') {
3701 16         59 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 425 my ($r, $x1) = @_;
3710            
3711 240 50       1042 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         344 return Rstats::Func::getin_list(@_);
3716             }
3717             elsif ($x1->{object_type} eq 'data.frame') {
3718 99         292 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         3 my $x1 = shift;
3729            
3730 1         2 my $levels_h = {};
3731 1         37 my $levels = Rstats::Func::levels($r, $x1)->values;
3732 1         9 for (my $i = 1; $i <= @$levels; $i++) {
3733 3         32 $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 70 my $r = shift;
3741            
3742 50         66 my $x1 = shift;
3743 50         545 my $x2 = Rstats::Func::to_object($r, shift);
3744            
3745 50         265 my $at = $x1->at;
3746 50 50       158 my $_indexs = ref $at eq 'ARRAY' ? $at : [$at];
3747 50         171 my ($poss, $x2_dim) = @{Rstats::Util::parse_index($r, $x1, 0, $_indexs)};
  50         159  
3748            
3749 50         354 my $type;
3750             my $x1_elements;
3751 50 100       1586 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         5 my $levels_h = Rstats::Func::_levels_h($r, $x1);
3756 1         4 for (my $i = 0; $i < @$poss; $i++) {
3757 2         3 my $pos = $poss->[$i];
3758 2         7 my $element = $x2_elements->[(($i + 1) % @$poss) - 1];
3759 2 50       27 if (Rstats::Func::is_na($r, $element)) {
3760 0         0 $x1_elements->[$pos] = Rstats::Func::c_logical($r, undef);
3761             }
3762             else {
3763 2         4 my $value = Rstats::Func::value($r, $element);
3764 2 50       7 if ($levels_h->{$value}) {
3765 2         18 $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         6 $type = $x1->get_type;
3774             }
3775             else {
3776             # Upgrade mode if type is different
3777 49 100       253 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         50  
3780 1         15 Rstats::Func::copy_attrs_to($r, $x1_tmp, $x1);
3781 1         25 $x1->vector($x1_tmp->vector);
3782            
3783 1         13 $type = $x1_tmp->get_type;
3784             }
3785             else {
3786 48         221 $type = $x1->get_type;
3787             }
3788              
3789 49         1781 $x1_elements = Rstats::Func::decompose($r, $x1);
3790              
3791 49         493 my $x2_elements = Rstats::Func::decompose($r, $x2);
3792 49         158 for (my $i = 0; $i < @$poss; $i++) {
3793 53         110 my $pos = $poss->[$i];
3794 53         447 $x1_elements->[$pos] = $x2_elements->[(($i + 1) % @$poss) - 1];
3795             }
3796             }
3797            
3798 50         642 $DB::single = 1;
3799 50         779 my $x1_tmp = Rstats::Func::compose($r, $type, $x1_elements);
3800 50         1171 $x1->vector($x1_tmp->vector);
3801 50         572 $x1->{type} = $x1_tmp->{type};
3802 50         89 $x1->{object_type} = $x1_tmp->{object_type};
3803            
3804 50         1101 return $x1;
3805             }
3806              
3807             sub sort {
3808 86     86 0 172 my $r = shift;
3809            
3810 86         416 my ($x1, $x_decreasing) = Rstats::Func::args_array($r, ['x1', 'decreasing', 'na.last'], @_);
3811            
3812 86 100       277 my $decreasing = defined $x_decreasing ? $x_decreasing->value : 0;
3813            
3814 86   100     134 my @x2_elements = grep { !Rstats::Func::is_na($r, $_) && !Rstats::Func::is_nan($r, $_) } @{Rstats::Func::decompose($r, $x1)};
  415         5313  
  86         1738  
3815            
3816             my $x3_elements = $decreasing
3817 3 50       18 ? [reverse sort { ($a > $b) ? 1 : ($a == $b) ? 0 : -1 } @x2_elements]
    100          
3818 86 50       592 : [sort { ($a > $b) ? 1 : ($a == $b) ? 0 : -1 } @x2_elements];
  362 100       2513  
    100          
3819              
3820 86         2968 return Rstats::Func::c_($r, @$x3_elements);
3821             }
3822              
3823             sub value {
3824 35725     35725 0 47272 my $r = shift;
3825 35725         45269 my $x1 = shift;
3826            
3827 35725         42069 my $e1;
3828 35725         169416 my $dim_values = Rstats::Func::values($r, $x1->dim_as_array);
3829 35725         539330 my $x1_elements = Rstats::Func::decompose($r, $x1);
3830 35725 100       84559 if (@_) {
3831 1838 100       4796 if (@$dim_values == 1) {
    100          
3832 118         215 $e1 = $x1_elements->[$_[0] - 1];
3833             }
3834             elsif (@$dim_values == 2) {
3835 807         2542 $e1 = $x1_elements->[($_[0] + $dim_values->[0] * ($_[1] - 1)) - 1];
3836             }
3837             else {
3838 913         5057 $e1 = Rstats::Func::decompose($r, $x1->get(@_))->[0];
3839             }
3840            
3841             }
3842             else {
3843 33887         55232 $e1 = $x1_elements->[0];
3844             }
3845            
3846 35725 50       396713 return defined $e1 ? Rstats::Func::first_value($r, $e1) : undef;
3847             }
3848              
3849             1;
3850              
3851             =head1 NAME
3852              
3853             Rstats::Func - Functions
3854