根据条件替换组

Posted

技术标签:

【中文标题】根据条件替换组【英文标题】:replace groups based on condition 【发布时间】:2019-05-20 01:11:02 【问题描述】:

我有一个 data.frame (df),参见示例,其中包含有关人员的信息。根据一个关键列 (sleutel),我知道人们是否住在一起(例如组成一个家庭)。现在,我需要创建新列,其中包含有关家庭“负责人”的信息。

     name   sex gzverh   sleutel gzhfd lft
1 Loekens   Man      6  1847LS 9     3  49
2   Kemel Vrouw      5 1847LK 10     2  18
3   Kemel   Man      5 1847LK 10     2  22
4 Boersma Vrouw      4 1847LK 10     2  52
5   Kemel   Man      2 1847LK 10     1  54

例如:第 5 行,Kemel,Male 和 gzhfd 1(= Kemel 家族的负责人)。他嫁给了夫人。 Boersma(同一个键)。我想改变一个新列(lfthb),其中包含所有家庭成员的户主年龄。所以应该变成这样:

     name  sex  gzverh   sleutel gzhfd lft lfthb
1 Loekens   Man      6  1847LS 9     3  49    NA
2   Kemel Vrouw      5 1847LK 10     2  18    54
3   Kemel   Man      5 1847LK 10     2  22    54
4 Boersma Vrouw      4 1847LK 10     2  52    54
5   Kemel   Man      2 1847LK 10     1  54    54

我使用group_bycase_whenif_else 语句的多种组合对dplyr 进行了多种尝试。我设法改变了一家之主的专栏。但不适用于其他成员。

例如,显然只改变了头部本身的值:

df <- df %>% mutate(lfthb  = case_when(sleutel == lag(sleutel) & gzhfd == 1 ~ lft))

但是如何在~ 之后包含gzhfd == 1

示例数据的输入:

structure(list(naam = c("Loekens", "Kemel", "Kemel", "Boersma", 
"Kemel"), gesl = c("Man", "Vrouw", "Man", "Vrouw", "Man"), gzverh = c(6L, 
5L, 5L, 4L, 2L), sleutel = c("1847LS 9", "1847LK 10", "1847LK 10", 
"1847LK 10", "1847LK 10"), gzhfd = c(3, 2, 2, 2, 1), lft = c(49, 
18, 22, 52, 54)), row.names = c(NA, 5L), class = "data.frame")

【问题讨论】:

【参考方案1】:

replaceifelse 的组合将完成这项工作,即,

library(tidyverse)

df %>% 
 group_by(sleutel) %>% 
 mutate(lfthb = ifelse(any(gzhfd == 1), replace(lft, gzhfd != 1, lft[gzhfd == 1]), NA))

给出,

# A tibble: 5 x 7
# Groups:   sleutel [2]
  naam    gesl  gzverh sleutel   gzhfd   lft lfthb
  <chr>   <chr>  <int> <chr>     <dbl> <dbl> <dbl>
1 Loekens Man        6 1847LS 9      3    49    NA
2 Kemel   Vrouw      5 1847LK 10     2    18    54
3 Kemel   Man        5 1847LK 10     2    22    54
4 Boersma Vrouw      4 1847LK 10     2    52    54
5 Kemel   Man        2 1847LK 10     1    54    54

正如@Ronak 提到的,我们可以省略replace 部分

df %>% 
 group_by(sleutel) %>% 
 mutate(lfthb = if (any(gzhfd == 1)) lft[gzhfd == 1] else NA)

【讨论】:

【参考方案2】:

data.table 方法(对于缺少数据的组返回 -INF 而不是 NA):

dt<-df %>% as.data.table() %>% 
  .[gzhfd==1, lfthb := lft, by="sleutel"] %>% 
  .[,lfthb:= max(lfthb,na.rm = T), by="sleutel"]

【讨论】:

以上是关于根据条件替换组的主要内容,如果未能解决你的问题,请参考以下文章

根据条件替换值

如何根据列组前缀替换列组的空白?

Pandas DataFrame:根据条件替换列中的所有值

如何根据字典替换熊猫系列中的字符串组,并将值作为列表?

Pandas Dataframe - 根据正则表达式条件替换所有单元格值

根据条件替换不同文件中的字符串