Как разделить каждый элемент в строке на соответствующее значение строки?

(Я хочу разделить каждый элемент в строке на соответствующее значение строки. Знаменатель должен иметь значение «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)
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
110
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Мы могли бы разделить каждую строку с первым значением в строке и взять по столбцам 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

(NA^(colSums(is.na(df[, -1])) == nrow(df))) * colSums(df[,-1]/df[[1]], na.rm = TRUE)

#     V1      V2      V3      V4      V5      V6      V7 
#     NA 0.00000 9.82143 3.69048 0.00000 0.84848 0.91883 

V1 должен быть NA и каким будет подход к таблице данных.

NUdu 30.05.2019 03:31

@NUdu обновил ответ. Теперь он также должен работать с data.table.

Ronak Shah 30.05.2019 03:43

попробуйте использовать цикл и преобразовать вывод в фрейм данных или список

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:8).

Gsingh 30.05.2019 04:22

Ваши данные:

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
Ответ принят как подходящий

Вот один из вариантов с tidyverse. Мы делим все столбцы, кроме столбца «Ac», на «Ac», затем summarise_all возвращаем sum, если присутствует какой-либо элемент, не относящийся к NA, или возвращаем 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))

Спасибо. Как я могу изменить это, если только одна строка является NA, делит число на соответствующий «Ac», как показано в моем выходном столбце V3.

NUdu 30.05.2019 17:16

@Nude Для меня ваш результат отображается 82.5/8.4# [1] 9.821429как тот, что у меня есть

akrun 30.05.2019 17:18

только что обновил мой вывод. Для столбцов V5, V6 и V7 мне нужно разделить на сумму обоих «Ac», если в обеих строках есть числа.

NUdu 30.05.2019 17:21

@NUdu Разве код не делает это прямо сейчас. Вам нужно df %>% summarise_at(-1, list(~ if (all(is.na(.))) NA else (sum(./sum(Ac), na.rm = TRUE)) ))

akrun 30.05.2019 17:22

Нет, код этого не делает. Например, для столбца V7 значение Output должно быть 2,904. ((5,2*6,6)+(1,1*8,4))/(6,6+8,4). Этот метод, только если данные существуют в обеих строках, в противном случае ваш метод правильный.

NUdu 30.05.2019 17:28

@NUdu Итак, вам нужен суммарный продукт

akrun 30.05.2019 17:33

да. ТОЛЬКО ЕСЛИ в обеих строках есть числа, в противном случае разделите на соответствующее значение «Ac».

NUdu 30.05.2019 17:34

@NUdu Как насчет этого df %>% summarise_at(-1, list(~ if (all(is.na(.))) NA else (sum(Ac* ., na.rm = TRUE)/sum(Ac, na.rm = TRUE)) )) V1 V2 V3 V4 V5 V6 V7 1 NA 0 46.2 17.36 0 2.464 2.904

akrun 30.05.2019 17:34

Нет. Например, ответ для столбца V3 должен быть 9,82 (82,5/8,4), потому что данные есть только в одной строке. Но V6, V7 верны, когда в обеих строках есть данные. Я предпочитаю метод таблицы данных.

NUdu 30.05.2019 17:37

@NUdu Непонятна логика. Вы делаете 82.5/8.4 как насчет части умножения?

akrun 30.05.2019 17:46

@NUdu Может быть это 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

akrun 30.05.2019 17:48

Спасибо. Именно этого я и добиваюсь. Не могли бы вы помочь мне с ответом таблицы данных, пожалуйста?

NUdu 30.05.2019 17:51

Другие вопросы по теме