我大约有60列不同的列,其中30列对应于其余30列的名称。我想根据其他对应值替换这30个列值。
df.wide<-data.frame(
title=c("A","B","C","D"),
IM.A=c(0.5,0.1,4.6,5.6),
LV.A=c(0.7,0,2.5,5),
IM.B=c(0.2,0.4,2.6,2.2),
LV.B=c(1,2,4.5,5),
IM.C=c(2,1,3,4),
LV.C=c(3,2,5,1)
)
我还有更多列-IM.D ~~ LM.D ~~数据中的每个标题。
df.long <- gather(df.wide, element,value, IM.A:LV.C)
df.long <- select(df.long, c("element"))
df.long <- unique(df.long)
lv <- as.data.frame(df.long[grep("LV", df.long$element), ])
im <- as.data.frame(df.long[grep("IM", df.long$element), ])
最终数据如下所示:
df.wide<-data.frame(
title=c("A","B","C","D"),
IM.A=c(0.5,0.1,4.6,5.6),
LV.A=c(0,0,2.5,5),
IM.B=c(0.2,0.4,2.6,2.2),
LV.B=c(0,0,4.5,0),
IM.C=c(2,1,3,4),
LV.C=c(0,0,5,1)
)
答案 0 :(得分:3)
也许以长格式存储数据:
library(data.table)
setDT(df.wide)
dt.long = melt(df.wide, meas=patterns(IM = "^IM", LV = "^LV"))
dt.long[, variable := c("A","B","C")[variable]]
title variable IM LV
1: A A 0.5 0.7
2: B A 0.1 0.0
3: C A 4.6 2.5
4: D A 5.6 5.0
5: A B 0.2 1.0
6: B B 0.4 2.0
7: C B 2.6 4.5
8: D B 2.2 5.0
9: A C 2.0 3.0
10: B C 1.0 2.0
11: C C 3.0 5.0
12: D C 4.0 1.0
从这里开始,很容易进行编辑:
dt.long[IM < 2.5, LV := 0]
如果要使用tidyr :据我所知,gather
不支持在转换为长格式时创建两列。函数的下一代pivot_longer
可能。
我建议尽可能长时间继续使用长格式的数据,以避免进一步困扰变量名,但是如果您需要恢复宽格式,则可以...
res = dcast(dt.long, title ~ variable, value.var=c("IM", "LV"), sep=".")
title IM_A IM_B IM_C LV_A LV_B LV_C
1: A 0.5 0.2 2 0.0 0.0 0
2: B 0.1 0.4 1 0.0 0.0 0
3: C 4.6 2.6 3 2.5 4.5 5
4: D 5.6 2.2 4 5.0 0.0 1
如果您想要相同的列顺序,则需要进一步的步骤:
setcolorder(res, names(df.wide))
title IM.A LV.A IM.B LV.B IM.C LV.C
1: A 0.5 0.0 0.2 0.0 2 0
2: B 0.1 0.0 0.4 0.0 1 0
3: C 4.6 2.5 2.6 4.5 3 5
4: D 5.6 5.0 2.2 0.0 4 1
答案 1 :(得分:1)
您可以使用ifelse(df.wide$IM.A < 2.5, 0, df.wide$LV.A)
。
对于所有列,假设您的变量按照df.wide
(IM.x
和LV.x
都紧随其后)中描述的方式隔开,则可以执行以下操作,其中3是LV
的第一列,最后LV
的列是7。
df.wide[,seq(3,7, by = 2)] <- sapply(seq(3,7, by = 2), function(x)
ifelse(df.wide[,x-1] < 2.5, 0, df.wide[,x])
)
但是正如@Frank指出的那样,您实际上应该尽可能长时间地使用长格式,以使这些操作更加简单。
答案 2 :(得分:1)
这是使用开发tidyr
pivot_
函数的一种方法。您可以通过运行devtools::install_github("tidyverse/tidyr")
获得这些。
这展示了枢轴功能的spec
功能,可让您灵活地指定重塑格式。它的工作方式是,规范的每一行都是原始数据帧的输入列(如果使用pivot_longer
)。 .name
列具有输入列名称,.value
列具有您希望各个输入列中的值进入的新列的名称。在这里,我们希望将以"IM"
开头的列中的所有值放入IM
列中,并以类似的方式将LV
放在其中。最后,我们指定其他变量如何映射到列(此处仅为letter
)。
这使我们可以快速pivot_longer
,用if_else
进行所需的替换,然后pivot_wider
回到原始格式。
library(tidyverse)
df.wide <- data.frame(
title = c("A", "B", "C", "D"),
IM.A = c(0.5, 0.1, 4.6, 5.6),
LV.A = c(0.7, 0, 2.5, 5),
IM.B = c(0.2, 0.4, 2.6, 2.2),
LV.B = c(1, 2, 4.5, 5),
IM.C = c(2, 1, 3, 4),
LV.C = c(3, 2, 5, 1)
)
spec <- tibble(
`.name` = df.wide %>% select(-title) %>% colnames(),
`.value` = str_extract(`.name`, "^.{2}"),
letter = str_extract(`.name`, ".{1}$")
)
df.wide %>%
pivot_longer(spec = spec) %>%
mutate(LV = if_else(IM < 2.5, 0, LV)) %>%
pivot_wider(spec = spec)
#> # A tibble: 4 x 7
#> title IM.A LV.A IM.B LV.B IM.C LV.C
#> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A 0.5 0 0.2 0 2 0
#> 2 B 0.1 0 0.4 0 1 0
#> 3 C 4.6 2.5 2.6 4.5 3 5
#> 4 D 5.6 5 2.2 0 4 1
由reprex package(v0.3.0)于2019-07-23创建