如何将行中的每个元素除以相应的行值?

时间:2019-05-30 01:22:23

标签: r

(我想将一行中的每个元素除以相应的行值。当存在行元素时,分母应为“ Ac”的值。

Ac    V1  V2  V3   V4  V5  V6  V7
6.6  NA  NA  NA   NA   0  5.6  5.2
8.4  NA  0   82.5 31   0  0    1.1

Output:

V1 V2    V3        V4       V5                            V6               V7     
NA 0/8.4 82.5/8.4 31/8.4  (0*6.6+0*6.6)/(6.6+8.4) (5.6*6.6+0*8.4)/(6.6+8.4) (5.2*6.6+1.1*8.4)/(6.6+8.4)

4 个答案:

答案 0 :(得分:2)

您的数据:

library(dplyr)

df <- data.frame(V1 = c(rep(NA,4), 0, 5.6, 5.2),
                 V2 = c(NA, 0 , 82.5, 31, 0, 0, 1.1))

df <- df %>% 
  t %>% as.data.frame() %>% 
  dplyr::mutate(Ac = c(6.6, 8.4)) %>% 
  dplyr::select(Ac, V1:V7)
df
> df
   Ac V1 V2   V3 V4 V5  V6  V7
1 6.6 NA NA   NA NA  0 5.6 5.2
2 8.4 NA  0 82.5 31  0 0.0 1.1
  • 答案:
resp <- df %>% 
  dplyr::select(-Ac) %>% 
  t %>% as.data.frame() %>% 
  dplyr::mutate(V1_1 = V1/df[1,1],
                V2_2 = V2/df[2,1]) %>% 
  dplyr::rowwise() %>% 
  dplyr::mutate(resp = ifelse(is.na(V1_1) & is.na(V2_2), NA,
                              sum(V1_1, V2_2, na.rm = T))) %>%
  dplyr::select(resp) %>% t %>% as.data.frame()
resp
> resp
     V1 V2       V3       V4 V5        V6        V7
resp NA  0 9.821429 3.690476  0 0.8484848 0.9188312

答案 1 :(得分:1)

尝试使用循环并将输出转换为数据框或列表

for (i in 2:8){

    temp1 = df[1,i]/df[1,1] 
    temp2 = df[2,i]/df[2,1]
    temp= ifelse(!is.na(temp1)&!is.na(temp2), temp1+temp2,
          ifelse(is.na(temp1) &!is.na(temp2), temp2,
          ifelse(!is.na(temp1) &is.na(temp2), temp1,NA)))
    assign(paste0("V", i-1), temp)
    rm(temp1, temp2, temp)
}
output <- c(V1, V2, V3, V4, V5, V6, V7)
output <- data.frame(output)

     output
1        NA
2 0.0000000
3 9.8214286
4 3.6904762
5 0.0000000
6 0.8484848
7 0.9188312

答案 2 :(得分:1)

这是tidyverse的一个选项。我们将除“ Ac”列以外的所有列均除以“ Ac”,然后如果存在任何非NA元素,则summarise_all返回sum,否则返回NA

library(tidyverse)
df %>%
  transmute_at(-1, list(~ ./Ac)) %>% 
  summarise_all(list(~ if(all(is.na(.))) NA else sum(.,na.rm = TRUE)))
#  V1 V2       V3       V4 V5        V6        V7
#1 NA  0 9.821429 3.690476  0 0.8484848 0.9188312

这也可以一步完成

df %>% 
  summarise_at(-1, list(~ if(all(is.na(.))) NA else (sum(./Ac, na.rm = TRUE)) ))
#  V1 V2       V3       V4 V5        V6        V7
#1 NA  0 9.821429 3.690476  0 0.8484848 0.9188312

更新

基于评论

df %>% 
    summarise_at(-1, list(~ if(all(is.na(.))) NA
       else if(sum(is.na(.)) == 1) (sum(./Ac, na.rm = TRUE)) 
      else (sum(Ac* ., na.rm = TRUE)/sum(Ac, na.rm = TRUE)) ))
#  V1 V2       V3       V4 V5    V6    V7
#1 NA  0 9.821429 3.690476  0 2.464 2.904

同样的方法也可以翻译为data.table

library(data.table)
setDT(df)[, lapply(.SD, function(x) if(all(is.na(x))) NA 
      else sum(x/Ac, na.rm = TRUE)), .SDcols = 2:ncol(df)]
#   V1 V2       V3       V4 V5        V6        V7
#1: NA  0 9.821429 3.690476  0 0.8484848 0.9188312

更新的data.table解决方案

setDT(df)[, lapply(.SD, function(x) if(all(is.na(x))) NA
       else if(sum(is.na(x)) == 1) (sum(x/Ac, na.rm = TRUE)) 
      else (sum(Ac* x, na.rm = TRUE)/sum(Ac, na.rm = TRUE)) ), .SDcols = 2:ncol(df)]
#   V1 V2       V3       V4 V5    V6    V7
#1: NA  0 9.821429 3.690476  0 2.464 2.904

数据

df <- structure(list(Ac = c(6.6, 8.4), V1 = c(NA_real_, NA_real_), 
    V2 = c(NA, 0), V3 = c(NA, 82.5), V4 = c(NA, 31), V5 = c(0, 
    0), V6 = c(5.6, 0), V7 = c(5.2, 1.1)), class = "data.frame", 
    row.names = c(NA, 
-2L))

答案 3 :(得分:0)

我们可以将每一行除以该行的第一个值,并按列进行layout_width

sum

如果我们想将第一个元素保留为colSums(df[, -1]/df[[1]], na.rm = TRUE) # V1 V2 V3 V4 V5 V6 V7 #0.00000 0.00000 9.82143 3.69048 0.00000 0.84848 0.91883

NA