Создание нового столбца на основе условия и подсчета по группе

#r #data.table #conditional-statements

#r #data.table #условные операторы

Вопрос:

У меня есть набор данных следующим образом:

 DT <- structure(list(ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16, 17, 18, 19, 20, 21, 22), Household = c(1, 1, 
1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13, 13, 
13), Main = c(1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 
1, 0, 1, 0, 1, 0), Variable = c(0.298830253959918, 0.696637114803799, 
0.222731978341587, 0.641245156419456, 0.145562076370066, 0.191365477844148, 
0.881263670583021, 0.314050677064662, 0.0770074657918196, 0.299236771626852, 
0.872886923047494, 0.289628283880055, 0.270138675264831, 0.910147226969786, 
0.582434831286225, 0.791627720726525, 0.852872802843926, 0.599723929185799, 
0.558087460306338, 0.862531226564633, 0.361200983684113, 0.765999001124532
)), row.names = c(NA, -22L), class = c("tbl_df", "tbl", "data.frame"
))
  

введите описание изображения здесь

К этому набору данных я хочу добавить дополнительный столбец. Если их более двух ID Household , я хочу Variable , чтобы значения Household членов, которые Main==0 суммировались и добавлялись в качестве новой переменной, добавлялись к строкам Household членов, у которых есть Main==1 , И НАОБОРОТ. Если другого Household элемента нет, значение равно 0 . Я бы предпочел сделать это в data.table , но я довольно быстро застреваю. Я начал следующим образом:

 # create a var with the nr of hh members
DTattempt <- setDT(DT)[, count:= .N, by=Household]

# if there is only 1 hh member, the value of New_Var = 0
DTattempt <- setDT(DTattempt)[count == 1, New_Var:= 0, by=Household]

# Now I try to fill in the value for the other rows, but here I get stuck
# I do not know how to tell R that it should only sum the other variables
DTattempt <- setDT(DTattempt)[count > 1, New_Var:=  ifelse(Main==1, sum(Variable, by=Household), sum(Variable, by=Household), by=Household]
  

Желаемый результат:

 DTnew <- structure(list(ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16, 17, 18, 19, 20, 21, 22), Household = c(1, 1, 
1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13, 13, 
13), Main = c(1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 
1, 0, 1, 0, 1, 0), Variable = c(0.29883025, 0.69663711, 0.22273198, 
0.64124516, 0.14556208, 0.19136548, 0.88126367, 0.31405068, 0.07700747, 
0.29923677, 0.87288692, 0.28962828, 0.27013868, 0.91014723, 0.58243483, 
0.79162772, 0.8528728, 0.59972393, 0.55808746, 0.86253123, 0.36120098, 
0.765999), New_Var = c(0.91936909, 0.29883025, 0.29883025, 0.14556208, 
0.64124516, 0.88126367, 0.19136548, 0.07700747, 0.31405068, 0, 
0, 0, 0.91014723, 0.27013868, 0, 0, 0, 0.55808746, 0.59972393, 
0.36120098, 1.62853023, 0.36120098)), row.names = c(NA, -22L), class = c("tbl_df", 
"tbl", "data.frame"))
  

введите описание изображения здесь

Ответ №1:

Следующее работает:

 setDT(DT)
DT[, nm := .N, by = .(Household, Main)]
    [, newVar := sum(Variable), by = .(Household, Main)]
    [, New_Var := sum(newVar/nm) - newVar, by = .(Household)]
    [, c("nm", "newVar") := list(NULL,NULL)]
    ID Household Main   Variable    New_Var
 1:  1         1    1 0.29883025 0.91936909
 2:  2         1    0 0.69663711 0.29883025
 3:  3         1    0 0.22273198 0.29883025
 4:  4         2    0 0.64124516 0.14556208
 5:  5         2    1 0.14556208 0.64124516
 6:  6         3    1 0.19136548 0.88126367
 7:  7         3    0 0.88126367 0.19136548
 8:  8         4    1 0.31405068 0.07700747
 9:  9         4    0 0.07700747 0.31405068
10: 10         5    0 0.29923677 0.00000000
11: 11         6    1 0.87288692 0.00000000
12: 12         7    1 0.28962828 0.00000000
13: 13         8    1 0.27013868 0.91014723
14: 14         8    0 0.91014723 0.27013868
15: 15         9    1 0.58243483 0.00000000
16: 16        10    1 0.79162772 0.00000000
17: 17        11    1 0.85287280 0.00000000
18: 18        12    0 0.59972393 0.55808746
19: 19        12    1 0.55808746 0.59972393
20: 20        13    0 0.86253123 0.36120098
21: 21        13    1 0.36120098 1.62853023
22: 22        13    0 0.76599900 0.36120098
  

Комментарии:

1. Большое вам спасибо! Очень классный способ решить эту проблему с помощью этой третьей строки.

2. Действительно, фантастический способ!

Ответ №2:

Я знаю, что мое решение может быть не идеальным, но оно должно работать

 library(tidyverse)

DT2 <- DT %>% arrange(Household, Main) %>%
  mutate(new = ifelse(Main == 0, as.complex(0 1i), 1)) %>%
  group_by(Household) %>%
  mutate(new = sum(new*Variable)) %>%
  group_by(Household, Main) %>%
  mutate(new = ifelse(Main == 1, Im(new), Re(new))) %>%
  ungroup() %>% arrange(ID)



  

Комментарии:

1. Большое вам спасибо! Принял другой ответ за то, что он немного менее сложный и является решением data.table. Один небольшой комментарий для строки ответа 10 должен быть равен нулю (потому что в домохозяйстве есть только один член).

2. О! В этом случае это проще. Я отредактирую ответ. Спасибо, что указали.

3. Для обмена значениями я использовал комплексные числа, которые можно рассматривать как двумерные числа