【问题标题】:Variable binning based on column value基于列值的变量分箱
【发布时间】:2017-08-14 23:16:55
【问题描述】:

这很难描述(因此标题模糊),所以我将只提供一些我想要的示例数据。我有两个数据框

set.seed(5)    
df = data.frame(ID  = sort(rep(c("2006_01", "2006_02", "2006_03", "2006_04"), length.out = 100)), 
            increment = rep(seq(from = 1, to = 25, by = 1), length.out = 100),
            Var1 = rnorm(100))

set.seed(23)
df2 = data.frame(ID  = sort(rep(c("2006_01", "2006_02", "2006_03", "2006_04"), length.out = 200)), 
             distance = rep(seq(from = 1, to = 50, by = 1), length.out = 200), 
             Var2 = rnorm(200))

它们本质上都是横断面,$increment$distance 是测量沿横断面进行测量的距离。较长的一个具有两倍的测量值,因为它具有更高的分辨率,但它代表相同的样带。我想根据横断面的距离比例加入他们。我使用以下代码计算了每个比例列:

df = ddply(df, "ID", transform, proportion = increment/max(increment))

df2 = ddply(df2, "ID", transform, proportion = distance/max(distance))

我想要的输出是加入两个数据帧(保持Var1Var2)。因为df2的分辨率更高,所以将它加入df的唯一方法是对它进行bin,但是我的真实数据不像样本数据那样规则,所以我需要根据proportion列动态bin这样它就可以计算df2 中位于df 中每组比例值之间的比例值的平均值

为了尝试和总结,我试图通过计算属于较低分辨率集分辨率的所有点的较高分辨率数据集的平均值来加入具有不同分辨率的数据集。

-编辑以尝试添加所需的输出-

输出数据帧的前几行如下所示:

ID        increment        Var1           Var2
2006_001         1  -0.84085548     -0.1207349
2006_001         2   1.38435934       1.353328
2006_001         3  -1.25549186       1.052048
2006_001         4   0.07014277      0.3705596

【问题讨论】:

  • 如果除了结构良好的样本数据之外,您还提供了一些预期的输出,那将会有所帮助。为此,我建议您调用set.seed,以便我们可以拥有相同随机数据,并且您可以列出所需输出的顶部(或中间或底部)几行。
  • @r2evans 更新了建议的信息。
  • 更好,谢谢。在浮点字段 (R FAQ 7.31) 上加入/合并可能会有问题。这是否足够可靠,您可以(例如)as.integer(100*distance/max(distance))increment 相同)并寻找相同的整数?或者您应该告诉我们您的垃圾箱是如何构造的。

标签: r


【解决方案1】:

一种方法是通过一些 tidyverse 包。

library(dplyr)
library(tidyr) # nest, unnest
library(purrr) # pmap

由于两个data.frames是不同的维度,我觉得nest把数据放到一个列里很好。

df2 <- df2 %>%
  group_by(ID) %>%
  mutate(
    proportion = (distance - min(distance)) / diff(range(distance))
  ) %>%
  nest(.key = "dist")
df2
# # A tibble: 4 × 2
#        ID              dist
#    <fctr>            <list>
# 1 2006_01 <tibble [50 × 3]>
# 2 2006_02 <tibble [50 × 3]>
# 3 2006_03 <tibble [50 × 3]>
# 4 2006_04 <tibble [50 × 3]>

df3 <- df %>%
  group_by(ID) %>%
  mutate(
    proportion = (increment - min(increment)) / diff(range(increment))
  ) %>%
  nest(.key = "incr") %>%
  left_join(df2, by = "ID") %>%
  mutate(
    incr = pmap(list(incr, dist),
                function(a, b) {
                  zz <- tail(a$proportion, n = -1) -
                    (tail(a$proportion, n = -1) - head(a$proportion, n = -1)) / 2
                  a$Var2 <- as.numeric(
                    by(b$Var2, cut(b$proportion, c(-1, zz, 2), labels = FALSE), mean)
                  )
                  a
                })
  )

既然已经在df2 中设置了东西,我们首先在df 中做同样的事情,并将它们并排合并:

df3 <- df %>%
  group_by(ID) %>%
  mutate(
    proportion = (increment - min(increment)) / diff(range(increment))
  ) %>%
  nest(.key = "incr") %>%
  left_join(df2, by = "ID")
df3
# # A tibble: 4 × 3
#        ID              incr              dist
#    <fctr>            <list>            <list>
# 1 2006_01 <tibble [25 × 3]> <tibble [50 × 3]>
# 2 2006_02 <tibble [25 × 3]> <tibble [50 × 3]>
# 3 2006_03 <tibble [25 × 3]> <tibble [50 × 3]>
# 4 2006_04 <tibble [25 × 3]> <tibble [50 × 3]>

请注意,当通过 ID 连接时,这允许我们将一个 data.frame 的 x 行与另一个 data.frame 的 y 行相关联。

df3 %>%
  mutate(
    incr = pmap(list(incr, dist),
                function(a, b) {
                  # offset between breaks, ...
                  breaks <- tail(a$proportion, n = -1) -
                    (tail(a$proportion, n = -1) - head(a$proportion, n = -1)) / 2
                  # ... with bookends to ensure 100% membership
                  breaks <- c(-1, breaks, 2)
                  a$Var2 <- as.numeric(
                    by(b$Var2, cut(b$proportion, breaks), mean)
                  )
                  a
                })
  ) %>%
  select(ID, incr) %>%
  unnest() %>%
  select(-proportion)
# # A tibble: 100 × 4
#         ID increment        Var1        Var2
#     <fctr>     <dbl>       <dbl>       <dbl>
# 1  2006_01         1 -0.84085548 -0.12073489
# 2  2006_01         2  1.38435934  1.35332759
# 3  2006_01         3 -1.25549186  1.05204780
# 4  2006_01         4  0.07014277  0.37055960
# 5  2006_01         5  1.71144087  0.81060839
# 6  2006_01         6 -0.60290798 -0.41412345
# 7  2006_01         7 -0.47216639  0.09643082
# 8  2006_01         8 -0.63537131 -0.45411977
# 9  2006_01         9 -0.28577363 -0.48124606
# 10 2006_01        10  0.13810822  0.34763251
# # ... with 90 more rows

【讨论】:

  • 哇,我需要花一点时间来完成所有这些工作,但它看起来像我想要的那样,谢谢!
猜你喜欢
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 2011-01-31
相关资源
最近更新 更多