Search code examples
rlistmatrixsum

R - Total sum of all named items in list elements


I am attempting to sum the number of atoms for each element in the chemical_formula vector:

chemical_formula <- c("CaF2", "Ca3(PO4)2", "FePO4", "KCl", "K3PO4", "K2SO4", "Mg3(PO4)2", "NaCl",
"Na3PO4", "Na2SO4", "SiO2", "CaSO4", "KAsO2", "KBr", "KI", "LiCl", "MnSO4", "CaS", "CuAsHO3",
"AlK(SO4)2", "(H2O)12", "ZnCl2", "CaCO3", "NaHCO3", "AsI3", "AuCl4Na", "Se", "K2Cr2O7")
cell_salts_atoms <- CHNOSZ::makeup(chemical_formula)

# > CHNOSZ::makeup(chemical_formula)
# [[1]]
# Ca  F 
#  1  2 
# 
# [[2]]
# Ca  O  P 
#  3  8  2 
# 
# [[3]]
# Fe  P  O 
#  1  1  4 
# 
# [[4]]
#  K Cl 
#  1  1 
# 
# [[5]]
# K P O 
# 3 1 4 
# 
# [[6]]
# K S O 
# 2 1 4 
# 
# [[7]]
# Mg  O  P 
#  3  8  2 
# 
# [[8]]
# Na Cl 
#  1  1 
# 
# [[9]]
# Na  P  O 
#  3  1  4 
# 
# [[10]]
# Na  S  O 
#  2  1  4 
# 
# [[11]]
# Si  O 
#  1  2 
# 
# [[12]]
# Ca  S  O 
#  1  1  4 
# 
# [[13]]
#  K As  O 
#  1  1  2 
# 
# [[14]]
#  K Br 
#  1  1 
# 
# [[15]]
# K I 
# 1 1 
# 
# [[16]]
# Li Cl 
#  1  1 
# 
# [[17]]
# Mn  S  O 
#  1  1  4
# 
# [[18]]
# Ca  S
#  1  1
# 
# [[19]]
# Cu As  H  O
#  1  1  1  3
# 
# [[20]]
# Al  K  O  S
#  1  1  8  2
# 
# [[21]]
#  H  O
# 24 12
# 
# [[22]]
# Zn Cl
#  1  2
# 
# [[23]]
# Ca  C  O
#  1  1  3
# 
# [[24]]
# Na  H  C  O
#  1  1  1  3
# 
# [[25]]
# As  I
#  1  3
# 
# [[26]]
# Au Cl Na
#  1  4  1
# 
# [[27]]
# Se
#  1
# 
# [[28]]
#  K Cr  O
#  2  2  7
cell_salts_atoms_matrix <- lapply(cell_salts_atoms, as.matrix)

# > cell_salts_atoms_matrix
# [[1]]
#    [,1]
# Ca    1
# F     2
# 
# [[2]]
#    [,1]
# Ca    3
# O     8
# P     2
# 
# [[3]]
#    [,1]
# Fe    1
# P     1
# O     4
# 
# [[4]]
#    [,1]
# K     1
# Cl    1
# 
# [[5]]
#   [,1]
# K    3
# P    1
# O    4
# 
# [[6]]
#   [,1]
# K    2
# S    1
# O    4
# 
# [[7]]
#    [,1]
# Mg    3
# O     8
# P     2
# 
# [[8]]
#    [,1]
# Na    1
# Cl    1
# 
# [[9]]
#    [,1]
# Na    3
# P     1
# O     4
# 
# [[10]]
#    [,1]
# Na    2
# S     1
# O     4
# 
# [[11]]
#    [,1]
# Si    1
# O     2
# 
# [[12]]
#    [,1]
# Ca    1
# S     1
# O     4
# 
# [[13]]
#    [,1]
# K     1
# As    1
# O     2
# 
# [[14]]
#    [,1]
# K     1
# Br    1
# 
# [[15]]
#   [,1]
# K    1
# I    1
# 
# [[16]]
#    [,1]
# Li    1
# Cl    1
# 
# [[17]]
#    [,1]
# Mn    1
# S     1
# O     4
# 
# [[18]]
#    [,1]
# Ca    1
# S     1
# 
# [[19]]
#    [,1]
# Cu    1
# As    1
# H     1
# O     3
# 
# [[20]]
#    [,1]
# Al    1
# K     1
# O     8
# S     2
# 
# [[21]]
#   [,1]
# H   24
# O   12
# 
# [[22]]
#    [,1]
# Zn    1
# Cl    2
# 
# [[23]]
#    [,1]
# Ca    1
# C     1
# O     3
# 
# [[24]]
#    [,1]
# Na    1
# H     1
# C     1
# O     3
# 
# [[25]]
#    [,1]
# As    1
# I     3
# 
# [[26]]
#    [,1]
# Au    1
# Cl    4
# Na    1
# 
# [[27]]
#    [,1]
# Se    1
# 
# [[28]]
#    [,1]
# K     2
# Cr    2
# O     7

I want the result to resemble the following:

Se 1
Au 1
As 2
Ca 6

I have tried cell_salts_atoms_sum <- lapply(cell_salts_atoms, sum); however, that only provides the total sum for each list element rather than sum of each named component.

What's the best method to produce the desired result?

UPDATE

The structure of the result does not matter, I just wanted a sum of the atoms.

Thus,

Se   Au   As   Ca
1    1    2    6

is also acceptable.


Solution

  • Please try

    library(CHNOSZ)
    
    cell_salts_atoms <- CHNOSZ::makeup(chemical_formula, sum=F)
    
    data <- map(cell_salts_atoms, \(x) {
      data.frame(val=x %>% as_vector()) %>% rownames_to_column(var='element')
    })
    
    data1 <- do.call(rbind, data) %>% arrange(element) %>% group_by(element) %>% summarise(sum=sum(val))
    
    
    # A tibble: 24 × 2
       element  sum
       <chr> <dbl>
     1 Al        1
     2 As        3
     3 Au        1
     4 Br        1
     5 C         2
     6 Ca        7
     7 Cl        9
     8 Cr        2
     9 Cu        1
    10 F         2
    # ℹ 14 more rows
    # ℹ Use `print(n = ...)` to see more rows