【问题标题】:Using map to iterate a function that left_joins使用 map 迭代 left_joins 的函数
【发布时间】:2021-05-22 07:38:06
【问题描述】:

我有两个看起来像这样的 df:

df1 = data.frame(CustomerId = c(1,1,2,2,3,3), Toaster = c(rep(1, 3), rep(0, 3)),radio=c(rep(0, 3), rep(1, 3)),year=c(2016,2018,2016,2019,2020,2021))
df2 = data.frame(CustomerId = c(1,1, 2,2, 3,3), State = c(rep("Alabama", 4), rep("Ohio", 2)),value=rnorm(6),year=seq(2016,2021,1))

df1 中的 Toasterradio 变量表示消费者购买烤面包机的年份。 一般来说,我的目标是从df1中的一些观察中提取关键信息,然后将它们加入到df2中。更准确地说,我想在 df2 中创建一个新变量,指示消费者购买Toasterradio 的第一年。在真实数据中,我需要为大量产品迭代此过程。 为了实现我的目标,我创建了一个可以满足我需求的函数。


first_buy <- function(var1){
  yo <- df1
  yo<-setDT(yo)[get(var1)==1
  ][order(year), buycount:= seq_len(.N), by = CustomerId
  ][buycount==1,first_buy_date:=year] 
  first_buy<-yo%>%select(CustomerId,first_buy_date)%>%
    distinct()
  df2 <- left_join(df2,first_buy) %>% 
    setnames("first_buy_date",paste("first_buy", (var1),sep = "_"))
    return(df2)
}

如果我在每个变量上单独使用该函数,它可以完美地提供预期的结果

df2<- first_buy("Toaster")
df_final_correct<- first_buy("radio")
print(df_final_correct)
   CustomerId   State      value year first_buy_Toaster first_buy_radio
1           1 Alabama -1.3507808 2016              2016              NA
2           1 Alabama -1.3507808 2016                NA              NA
3           1 Alabama -0.3957899 2017              2016              NA
4           1 Alabama -0.3957899 2017                NA              NA
5           2 Alabama  0.1681513 2018              2016            2019
6           2 Alabama  0.8138573 2019              2016            2019
7           3    Ohio -0.8039992 2020                NA            2020
8           3    Ohio -0.8039992 2020                NA              NA
9           3    Ohio  1.0181946 2021                NA            2020
10          3    Ohio  1.0181946 2021                NA              NA

但是,当我尝试对多个变量进行迭代时,该函数会提供不同的输出。


df1 = data.frame(CustomerId = c(1,1,2,2,3,3), Toaster = c(rep(1, 3), rep(0, 3)),radio=c(rep(0, 3), rep(1, 3)),year=c(2016,2018,2016,2019,2020,2021))
df2 = data.frame(CustomerId = c(1,1, 2,2, 3,3), State = c(rep("Alabama", 4), rep("Ohio", 2)),value=rnorm(6),year=seq(2016,2021,1))

itervar <- c("Toaster","radio")
df_final_wrong <- map_df(itervar,~first_buy(.x))
   CustomerId   State      value year first_buy_Toaster first_buy_radio
1           1 Alabama -1.2601968 2016              2016              NA
2           1 Alabama -1.2601968 2016                NA              NA
3           1 Alabama  0.9254294 2017              2016              NA
4           1 Alabama  0.9254294 2017                NA              NA
5           2 Alabama -0.3375396 2018              2016              NA#duplicated
6           2 Alabama -0.6909882 2019              2016              NA#duplicated
7           3    Ohio -0.1396262 2020                NA              NA
8           3    Ohio -1.3716387 2021                NA              NA
11          2 Alabama -0.3375396 2018                NA            2019 #duplicated
12          2 Alabama -0.6909882 2019                NA            2019#duplicated
13          3    Ohio -0.1396262 2020                NA            2020
15          3    Ohio -1.3716387 2021                NA            2020

问题在于它复制了CustomerId==2 的结果。 有谁知道我如何修改我的函数first_buy 以便它正确迭代?我不确定为什么 lef_join 在迭代中不能按预期工作。

非常感谢您的帮助

最好的

【问题讨论】:

    标签: r function loops merge left-join


    【解决方案1】:

    当你手动运行函数时:

    df2<- first_buy("Toaster")
    df_final_correct<- first_buy("radio")
    

    请注意,您将first_buy("Toaster") 的结果存储在df2 中,这会更改df2。当您运行first_buy("radio") 时,您有一个更改的df2,它与原来的df2 不同。 map 不会为您提供在第二次迭代中更改的 df2

    在每次迭代中更改df2 的简单解决方案是使用for 循环。

    for(item in itervar) {
      df2 <- first_buy(item)
    }
    df2
    
    #   CustomerId   State      value year first_buy_Toaster first_buy_radio
    #1           1 Alabama -0.1296113 2016              2016              NA
    #2           1 Alabama -0.1296113 2016                NA              NA
    #3           1 Alabama  0.3220200 2017              2016              NA
    #4           1 Alabama  0.3220200 2017                NA              NA
    #5           2 Alabama -0.5530528 2018              2016            2019
    #6           2 Alabama -0.2761895 2019              2016            2019
    #7           3    Ohio  1.9671128 2020                NA            2020
    #8           3    Ohio  1.9671128 2020                NA              NA
    #9           3    Ohio -0.2282965 2021                NA            2020
    #10          3    Ohio -0.2282965 2021                NA              NA
    

    【讨论】:

    • 很好,这太棒了!我唯一的问题是有没有办法使用地图或应用来做到这一点?或者有必要使用地图。我认为那张地图就像 for 循环一样工作。
    • 在大多数情况下,是的,map 用作 for 循环。但是,如果您的当前输出依赖于先前的输入 map 将不起作用。
    猜你喜欢
    • 2020-10-18
    • 2013-05-20
    • 2018-01-19
    • 2018-08-21
    • 2018-03-16
    • 2022-09-29
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多