使用列操作压缩宽数据框

问题描述 投票:0回答:1

我还在学习 R 并且想知道我是否有一种优雅的方式来操纵下面的 df 来实现 df2。

我不确定它是否应该用于此循环,但基本上对于每个 V(X)_Type(X) 列(不包括代理列),我想从第一行中减去每一行值当 Proxy_Type(X) 达到 99999 时行停止。

这可能听起来令人困惑,所以希望从 df 到所需 df2 的示例将有助于可视化我要问的内容。

Type1 <- c('ABC','DEF','GHI','JKL','MNO','PQR')
V1_Type1 <- c('1','0.5','1','0.2','3','4')
V2_Type1 <- c('2','0.5','1','0.3','3.2','4.1')
V3_Type1 <- c('3','0.6','1','0.4','3.3','4.3')
Proxy_Type1 <- c('0','99999','99999','99999','99999','99999')

Type2 <- c('DEF','GHI','JKL','MNO','PQR','STU')
V1_Type2 <- c('0.5','1','0.2','3','4','4.2')
V2_Type2 <- c('0.5','1','0.3','3.2','4.1','2.2')
V3_Type2 <- c('0.6','1','0.4','3.3','4.3','3')
Proxy_Type2 <- c('0','1.35','99999','99999','99999','99999')

Type3 <- c('GHI','JKL','MNO','PQR','STU','VWX')
V1_Type3 <- c('1','0.2','3','4','4.2','4.1')
V2_Type3 <- c('1','0.3','3.2','4.1','2.2','1.8')
V3_Type3 <- c('1','0.4','3.3','4.3','3','4.2')
Proxy_Type3 <- c('0','2.5','3','99999','99999','99999')



df <- data.frame(Type1,V1_Type1,V2_Type1,V3_Type1,Proxy_Type1,
                 Type2,V1_Type2,V2_Type2,V3_Type2,Proxy_Type2,
                 Type3,V1_Type3,V2_Type3,V3_Type3,Proxy_Type3)


To <- c('DEF','GHI','GHI')
From <- c('GHI','JKL','MNO')
V1 <- c('0.5','-0.8','2')
V2 <- c('0.5','-0.7','2.2')
V3 <- c('0.4','-0.6','2.3')

df2 <- data.frame(To,From,V1,V2,V3)

因此在所需的 df2 数据帧中,您可以看到没有 To 和 From“ABC”“DEF”,因为“DEF”代理是 99999,它会立即跳到“DEF”到“GHI”,然后 V1= (1- 0.5), V2=(1-0.5), V3=(1-0.6) 在 GHI 停止,因为 JKL 有 Proxy_Type2 = 99999。移动到 Type3,“GHI”到“JKL” V1=(0.2-1), V2=( 0.3-1),V3=(0.4-1) 然后“GHI”到“MNO”V1=(3-1),V2=(3.2-1),V3=(3.3-1)。该过程将在这里停止,因为 PQR 有 99999.

我有数百个这样的“类型”类型的列,我想在其中生成从 df 到 df2 的这种计算,手动耗时太多,非常感谢您的帮助。

谢谢

r dplyr tidyr rbind mutate
1个回答
0
投票

理解问题花了一些时间。如果您先tidy数据,解决方案很简单。在这种情况下,这意味着首先将

df
旋转更长的时间,以便
Type
是一个变量而不是每个变量名称的一部分。

假设数据按行号排序(下例中的

idx
),您只需在每个
Type
中执行以下操作(使用
group_by()
):在第一个Proxy == 99999之前保留行;做你的计算(当前行减去第一行);根据当前行和第一行设置
To
From
;并删除第一行。然后保留列
To
From
V1
...Vx,给你
df2

library(dplyr)
library(tidyr)

df %>%
  mutate(idx = row_number()) %>%
  pivot_longer(-idx) %>%
  mutate(
    Type = gsub(".*Type(\\d).*", "\\1", name),
    name = name %>%
      gsub("_Type\\d", "", .) %>%
      gsub("^Type\\d+$", "tofrom", .)
  ) %>%
  pivot_wider() %>%
  arrange(Type, idx) %>%
  group_by(Type) %>%
  filter(row_number() < which(Proxy == 99999)[1]) %>%
  mutate(
    across(matches("V"), \(x) as.numeric(x) - as.numeric(x)[1]),
    To = tofrom[1],
    From = tofrom
  ) %>%
  filter(row_number() != 1) %>%
  ungroup() %>%
  select(To, From, matches("V"))

# A tibble: 3 × 5
  To    From     V1    V2    V3
  <chr> <chr> <dbl> <dbl> <dbl>
1 DEF   GHI     0.5   0.5   0.4
2 GHI   JKL    -0.8  -0.7  -0.6
3 GHI   MNO     2     2.2   2.3
© www.soinside.com 2019 - 2024. All rights reserved.