r-quantities / units

Measurement units for R
https://r-quantities.github.io/units
173 stars 27 forks source link

Names are lost when units cancel but not when units do not cancel #305

Closed billdenney closed 1 year ago

billdenney commented 2 years ago

In the example below, names() are lost when the units cancel, but they are retained when units do not cancel. I think that the preferred behavior would keep the names().

library(units)
#> udunits database from C:/Users/Bill Denney/Documents/R/win-library/4.1/units/share/udunits/udunits2.xml
a <- setNames(set_units(1, "kg"), "A")
# names not shown on normal scalar print
a
#> 1 [kg]
# but they are still there
names(a)
#> [1] "A"

b <- setNames(set_units(c(1, 2), "kg"), c("A", "B"))
# names shown on vector print
b
#> Units: [kg]
#> A B 
#> 1 2
names(b)
#> [1] "A" "B"

d <- a/set_units(1, "mol")
d
#> 1 [kg/mol]
names(d)
#> [1] "A"

e <- b/set_units(1, "mol")
e
#> Units: [kg/mol]
#> A B 
#> 1 2
names(e)
#> [1] "A" "B"

# names are lost when units cancel to become unitless (for scalars)
f <- a/set_units(1, "mg")
f
#> 1e+06 [1]
names(f)
#> NULL

# names are lost when units cancel to become unitless (for vectors)
e <- b/set_units(1, "mg")
e
#> Units: [1]
#> [1] 1e+06 2e+06
names(e)
#> NULL

Created on 2022-02-23 by the reprex package (v2.0.1)

Enchufa2 commented 2 years ago

Thanks for the report, yes, we want to keep names.

billdenney commented 2 years ago

While thinking about this, I had an idea for a potential edge case. For normal R numeric vectors, they take the names of the first argument argument in vector/vector operations if they are the same length and the length of the longer argument if the lengths differ.

c(A=1, B=2)/c(D=3, E=4)
#>         A         B 
#> 0.3333333 0.5000000

c(A=1)/c(D=3, E=4)
#>         D         E 
#> 0.3333333 0.2500000

c(A=1, B=2, C=3, D=4)/c(D=3, E=4)
#>         A         B         C         D 
#> 0.3333333 0.5000000 1.0000000 1.0000000

c(D=3, E=4)/c(A=1, B=2, C=3, D=4)
#> A B C D 
#> 3 2 1 1

Created on 2022-02-23 by the reprex package (v2.0.1)

Enchufa2 commented 2 years ago

Interesting. It makes sense, since the shorter one is the one that gets recycled.

edzer commented 1 year ago
library(units)
# udunits database from /usr/share/xml/udunits/udunits2.xml
c(a = 3, b = 4) |> set_units(m) 
# Units: [m]
# a b 
# 3 4 
c(a = 3, b = 4) |> set_units(m) |> set_units(km)
# Units: [km]
# [1] 0.003 0.004
c(a = 3, b = 4) |> set_units(m) |> set_units(km) |> setNames(c("a", "b"))
# Units: [km]
#     a     b 
# 0.003 0.004 

It seems units get lost when unit conversion takes place, not when setting them.