如何在 dplyr 中应用并创建一个新列

How to tapply in dplyr and create a new column

我被 dplyr 困住了(又一次!)并试图在不死于尝试的情况下解决我的问题。

我的 df 的第一行是这样的:

df <- structure(list(fecha = c(1990, 1990, 1990, 1990, 1990, 1990, 
1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990), cientifico = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Argentina sphyraena", class = "factor"), 
    dem_sect = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L), .Label = c("AB", "EP", "FE", "MF", 
    "PA"), class = "factor"), sector = c("EPb", "EPc", "EPc", 
    "EPb", "EPa", "EPa", "EPb", "EPc", "EPb", "EPb", "EPb", "EPb", 
    "EPb", "EPb", "EPa"), md_area = c(3010.44, 665.88, 665.88, 
    3010.44, 1273.65, 1273.65, 3010.44, 665.88, 3010.44, 3010.44, 
    3010.44, 3010.44, 3010.44, 3010.44, 1273.65), md_peso = c(1.42957605985037, 
    1.04499099099099, 1.04499099099099, 1.42957605985037, 1.24025925925926, 
    1.24025925925926, 1.42957605985037, 1.04499099099099, 1.42957605985037, 
    1.42957605985037, 1.42957605985037, 1.42957605985037, 1.42957605985037, 
    1.42957605985037, 1.24025925925926), dummy = c(4303.65295361596, 
    695.838601081081, 695.838601081081, 4303.65295361596, 1579.65620555556, 
    1579.65620555556, 4303.65295361596, 695.838601081081, 4303.65295361596, 
    4303.65295361596, 4303.65295361596, 4303.65295361596, 4303.65295361596, 
    4303.65295361596, 1579.65620555556)), row.names = c(NA, -15L
), class = "data.frame")

我正在尝试将此 sumsect <- tapply(md_peso * md_area, as.factor(substr(names(sector), 1, 2)), sum)“翻译”成 dplyr。但是没有成功,尽管我尝试了很多方法。我添加了一列("dem_sect"),这将是as.factor(substr(names(sector), 1, 2))的结果,试图解决问题,但我失败了。

所需的输出将是一个带有新列的数据框:"sumsect"(具有相同的值(在本例中为 6579.148(md_peso 的总和) * md_area 按部门 (1579.6562 + 4303.6530 + 695.8386))

    fecha  cientifico          dem_sect sector md_area md_peso  dummy  sumsect
1   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
2   1990 Argentina sphyraena       EP    EPc  665.88 1.044991  695.8386 6579.148
3   1990 Argentina sphyraena       EP    EPc  665.88 1.044991  695.8386 6579.148
4   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
5   1990 Argentina sphyraena       EP    EPa 1273.65 1.240259 1579.6562 6579.148
6   1990 Argentina sphyraena       EP    EPa 1273.65 1.240259 1579.6562 6579.148
7   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
8   1990 Argentina sphyraena       EP    EPc  665.88 1.044991  695.8386 6579.148
9   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
10  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
11  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
12  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
13  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
14  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
15  1990 Argentina sphyraena       EP    EPa 1273.65 1.240259 1579.6562 6579.148

我们非常欢迎任何提示。提前致谢

你可以改变然后总结 dummy

unique
df |> 
  mutate(sumsect = sum(unique(dummy)))

如果您依赖 md_area 和 md_peso,您可以使用:

df |> 
  mutate(sumsect = sum(unique(md_area * md_peso)))

如果您要使用 dpylr,则不需要 tapply。如果您要使用 dpylr.

,则不需要 tapply
library(tidyverse)
df %>% # target dataframe
  cbind( # we will join a value as a new column for every row
    df %>% # work with dataframe df
    group_by(sector) %>% # calculate by sector
    summarise(sumsect = unique(md_area*md_peso)) %>% # the md_area*md _peso
    ungroup() %>% # remove grouping
    summarise(sumsect = sum(sumsect)) # sum the 3 calculated values
  )

输出:

   fecha          cientifico dem_sect sector md_area  md_peso     dummy  sumsect
1   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
2   1990 Argentina sphyraena       EP    EPc  665.88 1.044991  695.8386 6579.148
3   1990 Argentina sphyraena       EP    EPc  665.88 1.044991  695.8386 6579.148
4   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
5   1990 Argentina sphyraena       EP    EPa 1273.65 1.240259 1579.6562 6579.148
6   1990 Argentina sphyraena       EP    EPa 1273.65 1.240259 1579.6562 6579.148
7   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
8   1990 Argentina sphyraena       EP    EPc  665.88 1.044991  695.8386 6579.148
9   1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
10  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
11  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
12  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
13  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
14  1990 Argentina sphyraena       EP    EPb 3010.44 1.429576 4303.6530 6579.148
15  1990 Argentina sphyraena       EP    EPa 1273.65 1.240259 1579.6562 6579.148

如果您可能希望通过分组的 cientificofecha 或两者来计算 sumsect,您可以将它们分组。在你的例子中只有一个。

在您的示例中,您只有 1 个日期和 1 个科学家。如果您希望这些列的每个级别的 sumsect 都不同,请不要忘记也对这些列进行分组。

更新:看到@Jahi Zamy answer+1 也可以不使用分组:分组将有机会控制真实数据集中的不同组:

df %>% 
  mutate(sumsect = sum(unique( md_peso * md_area)))

第一个回答: 您可以使用 dplyr 这样做:诀窍是使用 group_by,然后使用 ungroup() 并与 unique 值相加。如果您想对特定组求和,则使用 group_by 而不是 ungroup 所需的组:

df %>% 
  group_by(sector) %>% 
  mutate(y = md_peso * md_area) %>% 
  ungroup() %>% 
  mutate(sumsect = sum(unique(y)), .keep="unused")
   fecha cientifico          dem_sect sector md_area md_peso dummy sumsect
   <dbl> <fct>               <fct>    <chr>    <dbl>   <dbl> <dbl>   <dbl>
 1  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
 2  1990 Argentina sphyraena EP       EPc       666.    1.04  696.   6579.
 3  1990 Argentina sphyraena EP       EPc       666.    1.04  696.   6579.
 4  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
 5  1990 Argentina sphyraena EP       EPa      1274.    1.24 1580.   6579.
 6  1990 Argentina sphyraena EP       EPa      1274.    1.24 1580.   6579.
 7  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
 8  1990 Argentina sphyraena EP       EPc       666.    1.04  696.   6579.
 9  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
10  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
11  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
12  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
13  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
14  1990 Argentina sphyraena EP       EPb      3010.    1.43 4304.   6579.
15  1990 Argentina sphyraena EP       EPa      1274.    1.24 1580.   6579.