如何根据其他数据将默认日期更改为正确日期?

时间:2017-09-07 13:13:58

标签: r dataframe

我有一个看起来像这样的数据框,只有更多的附加列,这对于这个问题并不重要。

  DAY MONTH YEAR NAME   SURNAME
1   1     1 2012 Luke Skywalker
2   3     4 2012 Luke Skywalker
3   3     4 2012 Luke Skywalker
4   1     8 2013  Han      Solo
5   5     8 2013  Han      Solo
6   5     8 2013  Han      Solo
7   1     1 2012  Ben      Solo
8   6     2 2011 Leia    Organa

DAYMONTHYEAR表示此人的出生日期。但由于缺少某些日期(但它们有多年),如果没有生日,则默认为DAY=1YEAR=1。同一年份同一年内出现同一个名称不止一次。当然,有些人可能会在1.1.year

上过生日

我想要做的是,搜索那些具有生日默认值并将其设置为正确的那些。

我做的是:我创建了一个子数据框,其中只包含那些行,1.1.year在同一年只发生过一次相同的名称(如果它不止一次,我们可以假设这是他的出生日)和人数在哪里(在整个df中有多少同名,姓和年的人)大于1.如果不是,我们只有一行这个日期我们什么也说不出来。 (就像她Ben)的情况一样。如果只有两次出现,一次是1.1.year,一次没有,那么非默认值(1.1)优先。

现在我计划迭代这个新的子数据框,匹配每个姓氏和年份,并用一个替换日期,这是该年名称中最常见的,但我不知道如何做到这一点有效率的。数据框很大,因此for循环可能是不可能的。

我想要的是:

  DAY MONTH YEAR NAME   SURNAME
1   3     4 2012 Luke Skywalker
2   3     4 2012 Luke Skywalker
3   3     4 2012 Luke Skywalker
4   5     8 2013  Han      Solo
5   5     8 2013  Han      Solo
6   5     8 2013  Han      Solo
7   1     1 2012  Ben      Solo
8   6     2 2011 Leia    Organa

1 个答案:

答案 0 :(得分:2)

使用dplyr的解决方案。请注意,当数据集中的流行率存在关联时,此代码不会处理这种情况。它假设记录中只有一个日期最丰富,并选择一条记录来替换不占优势的记录。

library(dplyr)
dt2 <- dt %>% 
  mutate(ID = 1:n()) %>%
  group_by(NAME, SURNAME, DAY, MONTH, YEAR) %>%
  mutate(N = n()) %>%
  ungroup() %>%
  group_by(NAME, SURNAME) %>%
  mutate_at(vars(DAY, MONTH), funs(ifelse(N != max(N), NA, .))) %>%
  arrange(DAY, MONTH) %>%
  mutate_at(vars(DAY, MONTH), funs(ifelse(is.na(.), first(.), .))) %>%
  arrange(ID) %>%
  select(-N, -ID)
dt2
# A tibble: 8 x 5
# Groups:   NAME, SURNAME [4]
    DAY MONTH  YEAR  NAME   SURNAME
  <dbl> <dbl> <int> <chr>     <chr>
1     3     4  2012  Luke Skywalker
2     3     4  2012  Luke Skywalker
3     3     4  2012  Luke Skywalker
4     5     8  2013   Han      Solo
5     5     8  2013   Han      Solo
6     5     8  2013   Han      Solo
7     1     1  2012   Ben      Solo
8     6     2  2011  Leia    Organa

DATA

dt <- read.table(text = "  DAY MONTH YEAR NAME   SURNAME
1   1     1 2012 Luke Skywalker
                 2   3     4 2012 Luke Skywalker
                 3   3     4 2012 Luke Skywalker
                 4   1     8 2013  Han      Solo
                 5   5     8 2013  Han      Solo
                 6   5     8 2013  Han      Solo
                 7   1     1 2012  Ben      Solo
                 8   6     2 2011 Leia    Organa",
                 header = TRUE, stringsAsFactors = FALSE)