【问题标题】:Updating Values in R dataframe更新 R 数据框中的值
【发布时间】:2018-11-30 13:53:54
【问题描述】:

我是 R 编程新手,我想知道是否有办法通过比较 2 个文件来更新值。

例如,我有我的主表 df_table1:

Date           Metric1     Metric2     Metric3
1/1/2018       25          4.6         49
2/1/2018       6           3.6         67
3/1/2018       18          2.6         36
4/1/2018       56          3.6         29

我正在迭代地浏览文件夹中的各种文件,我碰巧有一个文件也包含一些具有相同日期值的重叠数据,df_table2:

Date           Metric1    Metric2      Metric3
3/1/2018       19         2.9          47
4/1/2018       78         5.7          35
5/1/2018       46         3.3          29

组合数据文件的常用方法是使用 rbind(),但我相信这会为 df_table2 中的 2 个日期创建重复值。

有没有办法有效地进行比较,检查我所有后续文件的重叠日期,并根据 df_table1 中的日期替换它们的相应值?

理想情况下,如果 df_table2 中的所有指标的值都大于 df_table1 中的值,那么如果有一种方法只进行替换会更好。

最后,我希望最终输出是 df_table1 和 df_table2 通过某种特殊的 rbind() 函数的组合,其值从 df_table2 更新而没有重复:

Date           Metric1    Metric2      Metric3
1/1/2018       25         4.6          49
2/1/2018       6          3.6          67
3/1/2018       19         2.9          47       #updated from df_table2
4/1/2018       78         5.7          35       #updated from df_table2
5/1/2018       46         3.3          29       #new value from df_table2

谢谢!

【问题讨论】:

  • 我不清楚最终的结果应该是什么。您希望使用 df_table1 的相应值更新 df_table2(理想情况下,仅当给定指标的 df_table1 中的值低于 df_table2 中的值时)。之后你想用 df_table2 做什么?
  • 嗨@SAFEX,感谢您指出这一点。我进行了一些更改以显示我想要的所需输出。比较完成后我并不完全需要 df_table2 ,并且以某种方式 rbind() 更新和新值,如果这有意义的话?

标签: r compare


【解决方案1】:

我们先定义数据(以后请自己做,方便别人帮助你):

df_table1= data.frame(Date=c('1/1/2018','2/1/2018','3/1/2018','4/1/2018'), 
Metric1 = c(25,6,18,56),
Metric2 = c(4.6,3.6,2.6,3.6),
Metric3 = c(49,67,36,29))

df_table2= data.frame(Date=c('3/1/2018','4/1/2018','5/1/2018'), Metric1 = c(19,78,46),
Metric2 = c(2.9,5.7,3.3),
Metric3 = c(48,35,29))

接下来我将合并表格,然后重新创建您需要的变量。我给你写的第一个,其他的应该很容易。除了使用is.na(),您还可以比较哪个变量更大并选择您想要的变量。

df = merge(df_table1, df_table2, by='Date', all=TRUE)
df$Metric1 = df$Metric1.y
df$Metric1[is.na(df$Metric1)]  = df$Metric1.x[is.na(df$Metric1)] 
df
   Date    Metric1.x Metric2.x Metric3.x Metric1.y Metric2.y Metric3.y Metric1
1 1/1/2018        25       4.6        49        NA        NA        NA      25
2 2/1/2018         6       3.6        67        NA        NA        NA       6
3 3/1/2018        18       2.6        36        19       2.9        48      19
4 4/1/2018        56       3.6        29        78       5.7        35      78
5 5/1/2018        NA        NA        NA        46       3.3        29      46

【讨论】:

  • 感谢您的指导。指标应该全部在一个数据框中,而不是全部是单独的向量。我正在寻找一种解决方案,可以帮助我执行 rbind() 同时允许更新值。希望我的澄清有助于使问题更有意义
  • 不确定我是否理解。我的解决方案将“最终值”存储在一个数据框中(称为df)。如果df_table2 得到一个新的观察值(例如6/1/2018),只需重新运行代码,它就会得到所有数据点。
【解决方案2】:

使用dplyr

rbind(df_table1,df_table2) %>% group_by(Date) %>% filter(Metric1==max(Metric1))
# A tibble: 5 x 4
# Groups:   Date [5]
  Date     Metric1 Metric2 Metric3
  <chr>      <dbl>   <dbl>   <dbl>
1 1/1/2018     25.    4.60     49.
2 2/1/2018      6.    3.60     67.
3 3/1/2018     19.    2.90     48.
4 4/1/2018     78.    5.70     35.
5 5/1/2018     46.    3.30     29.

请注意,这假设如果一个表中的 Metric1 比另一个表中的大,那么所有其他指标也是如此。我不清楚如果不是这种情况会发生什么。

这是一个奇怪的复杂代码,它将为两个表中的每个日期保留一行,保留所有指标都大于另一行的行,或者,如果两行都不匹配该规则,它将保留该行来自表 1:

首先,让我们稍微改变一下数据:

df_table1= data.frame(Date=c('1/1/2018','2/1/2018','3/1/2018','4/1/2018'), 
                      Metric1 = c(25,6,18,56),
                      Metric2 = c(4.6,3.6,2.6,6.3),
                      Metric3 = c(49,67,36,29), stringsAsFactors = FALSE)

df_table2= data.frame(Date=c('3/1/2018','4/1/2018','5/1/2018'), Metric1 = c(19,78,46),
                      Metric2 = c(2.9,5.7,3.3),
                      Metric3 = c(48,35,29), stringsAsFactors = FALSE)

现在,在 1 月 4 日的一行中,指标 2 的一行较高,而另一行的其他指标较高。

rbind(df_table1,df_table2) %>% 
group_by(Date) %>% 
mutate(keeper=(Metric1==max(Metric1) & Metric2==max(Metric2) & Metric3==max(Metric3))) %>% 
group_by(Date,keeper) %>% 
filter(row_number()==1) %>% 
group_by(Date) %>% add_count() %>% 
mutate(keeper=ifelse(n==1,TRUE,keeper)) %>% 
filter(keeper) %>% select(-keeper, -n)
# A tibble: 5 x 4
# Groups:   Date [5]
  Date     Metric1 Metric2 Metric3
  <chr>      <dbl>   <dbl>   <dbl>
1 1/1/2018     25.    4.60     49.
2 2/1/2018      6.    3.60     67.
3 4/1/2018     56.    6.30     29.
4 3/1/2018     19.    2.90     48.
5 5/1/2018     46.    3.30     29.

我确信有一种更优雅的方法可以实现这一点,但我不知道它是什么 - 我经过大量的试验和错误得到了这个......

最后,如果您决定在存在重复日期的情况下只保留 table1 版本,而不管指标如何,请执行以下操作:

rbind(df_table1,df_table2) %>%  filter(!duplicated(Date))
      Date Metric1 Metric2 Metric3
1 1/1/2018      25     4.6      49
2 2/1/2018       6     3.6      67
3 3/1/2018      18     2.6      36
4 4/1/2018      56     6.3      29
5 5/1/2018      46     3.3      29

【讨论】:

  • 谢谢!我将尝试阅读 dplyr。所以如果我不需要关心 Metric1 是否更大,我只需要删除那个过滤器?
  • 如果您删除过滤器,您仍然会有重复项 - 您需要以某种方式将它们过滤掉......
【解决方案3】:

这应该适合你

library(dplyr)
df_new <- df_table1%>%
  anti_join(df_table2, by = c('Date'))%>%
  rbind(data= . ,df_table2)

【讨论】:

  • 为什么被降级?这完全根据答案的要求产生。反连接将使您拥有 df1 而不是 df2 中的内容。由于您遗漏了两个表之间的共同点,您现在可以从 df2 获取所有数据并将其与 df1 绑定。这消除了重复,并确保您从 df2 获得更新的信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-18
相关资源
最近更新 更多