Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adjust vector subset values according to certain rules

Tags:

r

I am trying to code a function that converts Chinese numerals to Arabic. The idea is to get a set of scaled_digit vectors and a set of scale_factor vectors, multiply and add them up to generate the desired output.

digit=c('〇'=0,'一'=1,'二'=2,'三'=3,'四'=4,'五'=5,'六'=6,'七'=7,'八'=8,'九'=9)
scale=c('十'=10^1,'百'=10^2,'千'=10^3,'萬'=10^4,'億'=10^8,'兆'=10^12)

One of the problems I encounter is this:

When I have a number that is a few hundred 10^4s (萬) and a few thousand 10^12s (兆), I am left with a scale-factor vector that is as follows:

scale_factor=
structure(c(1000, 1e+12, 100, 10, 10000, 1000, 100, 10), .Names = c("千", 
"兆", "百", "十", "萬", "千", "百", "十"))

   [千]     兆    [百]    [十]    萬    千    百    十 
  [1e+03] 1e+12 [1e+02] [1e+01] 1e+04 1e+03 1e+02 1e+01

Scale factors to be adjusted have been marked by [ ].

The positions of the cardinal scale_factors can be found with the following code:

cardinal_scale_factor=which(diff(scale_factor)>=0, T)+1

兆 萬 
 2  5

How do I code so that scale_factor[1] and scale_factor[3:4] can be multiplied by scale_factor[2] and [5] respectively?


Expected result:

   [千]     兆    [百]    [十]    萬    千    百    十 
  [1e+15] 1e+12 [1e+06] [1e+05] 1e+04 1e+03 1e+02 1e+01 
like image 620
Sati Avatar asked Dec 20 '25 09:12

Sati


1 Answers

A possible solution:

w1 <- which(rev(cummax(rev(scale_factor)) > rev(scale_factor)))

grp <- cumsum(c(1,diff(w1)) > 1) + 1

w2 <- aggregate(w1, list(grp), max)[[2]] + 1

scale_factor[w1] <- scale_factor[w1] * scale_factor[w2][grp]

which gives:

> scale_factor
   千    兆    百    十    萬    千    百    十 
1e+15 1e+12 1e+06 1e+05 1e+04 1e+03 1e+02 1e+01

What this does:

  1. With cummax(rev(scale_factor)) you get the cummulative maximum of the reversed scale.
  2. Comparing that with the reversed scale (cummax(rev(scale_factor)) > rev(scale_factor)) gives a logical vector.
  3. Wrapping the logical vector from step 2 in rev and which subsequently, wou get an index vector of positions w1 that do not conform to the decreasing condition.
  4. With cumsum(c(1,diff(w1)) > 1) + 1 you can group these positions for case the 3rd and 4th values in the example data.
  5. With aggregate(w1, list(grp), function(x) max(x) + 1)[[2]] you determine the positions of the multipliers.
  6. Finally, you multiply the values in scale_factor as determined in w1 with the multipliers from w2. You need to index w2 with the group numbers from grp.
like image 103
Jaap Avatar answered Dec 22 '25 00:12

Jaap



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!