繁体   English   中英

如果组中的其他两个值是 NA,则分组并替换组中的值

[英]Group by and replace a value in group if two other values in group are NA

我有以下 df:

df <- data.frame(comp_name = c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B"),
                 year = c("2016", "2016", "2016", "2017","2017", "2017", "2016","2016", "2016", "2017", "2017", "2017"),
                 indicator = c("total_revenue", "overseas_revenue", "domestic_revenue", "total_revenue", "overseas_revenue", "domestic_revenue","total_revenue", "overseas_revenue", "domestic_revenue","total_revenue", "overseas_revenue", "domestic_revenue"),
                 value = c(100, NA, NA, 100, 20, 80, 90, NA, 60, 90, NA, NA))

df 看起来像这样:

公司名称 指标 价值
一种 2016年 总收入 100
一种 2016年 海外收入 北美
一种 2016年 国内收入 北美
一种 2017年 总收入 100
一种 2017年 海外收入 20
一种 2017年 国内收入 80
2016年 总收入 90后
2016年 海外收入 北美
2016年 国内收入 60
2017年 总收入 90后
2017年 海外收入 北美
2017年 国内收入 北美

我想按 comp_name 和年份分组并将以下规则应用于每个组:如果 overseas_revenue 和 domestic_revenue 的值为 NA,则将 domestic_revenue 的值设置为等于 total_revenue 的值,否则什么也不做。

生成的 df 应如下所示:

公司名称 指标 价值
一种 2016年 总收入 100
一种 2016年 海外收入 北美
一种 2016年 国内收入 100
一种 2017年 总收入 100
一种 2017年 海外收入 20
一种 2017年 国内收入 80
2016年 总收入 90后
2016年 海外收入 北美
2016年 国内收入 60
2017年 总收入 90后
2017年 海外收入 北美
2017年 国内收入 90后

我的实际数据集有 500k + 行和 12 个不同的指标,但我一直无法找到有效的方法。 任何帮助将不胜感激-谢谢!

你可以用两个支点来做到这一点:

library(dplyr)
library(tidyr)
  df <- data.frame(comp_name = c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B"),
                   year = c("2016", "2016", "2016", "2017","2017", "2017", "2016","2016", "2016", "2017", "2017", "2017"),
                   indicator = c("total_revenue", "overseas_revenue", "domestic_revenue", "total_revenue", "overseas_revenue", "domestic_revenue","total_revenue", "overseas_revenue", "domestic_revenue","total_revenue", "overseas_revenue", "domestic_revenue"),
                   value = c(100, NA, NA, 100, 20, 80, 90, NA, 60, 90, NA, NA))
  df %>% 
  pivot_wider(names_from="indicator", 
              values_from = "value") %>% 
  mutate(domestic_revenue = case_when(
    is.na(overseas_revenue) & is.na(domestic_revenue) ~ total_revenue, 
    TRUE ~ domestic_revenue)) %>% 
  pivot_longer(-c(comp_name, year), 
               names_to = "indicator", 
               values_to = "value")
#> # A tibble: 12 × 4
#>    comp_name year  indicator        value
#>    <chr>     <chr> <chr>            <dbl>
#>  1 A         2016  total_revenue      100
#>  2 A         2016  overseas_revenue    NA
#>  3 A         2016  domestic_revenue   100
#>  4 A         2017  total_revenue      100
#>  5 A         2017  overseas_revenue    20
#>  6 A         2017  domestic_revenue    80
#>  7 B         2016  total_revenue       90
#>  8 B         2016  overseas_revenue    NA
#>  9 B         2016  domestic_revenue    60
#> 10 B         2017  total_revenue       90
#> 11 B         2017  overseas_revenue    NA
#> 12 B         2017  domestic_revenue    90

reprex package (v2.0.1) 创建于 2022-04-28

require(tidyverse)
df %>%
  spread(indicator, value) %>%
  mutate(domestic_revenue = case_when(
    is.na(domestic_revenue) & is.na(overseas_revenue) ~ total_revenue, 
    TRUE ~ domestic_revenue
  )) %>% 
  gather(c(-comp_name, -year), key = indicator, value = value) %>%  
  arrange(comp_name, year)

# A tibble: 12 x 4
   comp_name year  indicator        value
   <chr>     <chr> <chr>            <dbl>
 1 A         2016  domestic_revenue   100
 2 A         2016  overseas_revenue    NA
 3 A         2016  total_revenue      100
 4 A         2017  domestic_revenue    80
 5 A         2017  overseas_revenue    20
 6 A         2017  total_revenue      100
 7 B         2016  domestic_revenue    60
 8 B         2016  overseas_revenue    NA
 9 B         2016  total_revenue       90
10 B         2017  domestic_revenue    90
11 B         2017  overseas_revenue    NA
12 B         2017  total_revenue       90

我认为最好创建一个非常简单的 function 来处理您想要的调整,然后按组应用该 function。 这将比旋转快得多。

f <- function(i,v) {
  if(all(is.na(v[grepl("^(o|d)",i)]))) v[i=="domestic_revenue"]=v[i=="total_revenue"]
  return(v)
}

使用 data.table(会很快)

setDT(df)[,value:=f(indicator,value), by=.(comp_name, year)]

使用 dplyr(会更慢,但仍然比旋转更快)

df %>% 
  group_by(comp_name,year) %>%
  mutate(value=f(indicator,value))

Output:

    comp_name   year        indicator value
       <char> <char>           <char> <num>
 1:         A   2016    total_revenue   100
 2:         A   2016 overseas_revenue    NA
 3:         A   2016 domestic_revenue   100
 4:         A   2017    total_revenue   100
 5:         A   2017 overseas_revenue    20
 6:         A   2017 domestic_revenue    80
 7:         B   2016    total_revenue    90
 8:         B   2016 overseas_revenue    NA
 9:         B   2016 domestic_revenue    60
10:         B   2017    total_revenue    90
11:         B   2017 overseas_revenue    NA
12:         B   2017 domestic_revenue    90

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM