我的数据
conc_data=structure(list(kod_nar.id = c(1L, 3L, 2L),
x123_1 = c(0L, 0L, 0L),
x124_2 = c(0, 0.123, 0.122),
x125_3 = 0:2,
x126_4 = c(0, 0.234, 0.99)),
.Names = c("kod_nar.id", "x123_1", "x124_2", "x125_3", "x126_4"),
class = "data.frame", row.names = c(NA, -3L))
这里有4列,但是每2列需要合并为一列,并具有第一列的名称。 换句话说,每对列都应合并在一起,并串联数字的值。结果,我们在数据框中将只有2列。数据帧中的每一列都有一对。列数是偶数。列的顺序是第一对,第二对,依此类推
I.E。输出
kod_nar.id x123_1 x125_3
1 1 0 0
2 3 0(0.123) 1(0.234)
3 2 0(0.122) 2(0.99)
如何做到?
答案 0 :(得分:4)
一种选择是遍历列集,使用sprintf
设置感兴趣的列的格式,并使用cbind
填充第一列
out <- cbind(conc_data[1], sapply(list(2:3, 4:5),
function(i) sprintf("%d(%f)",
round(conc_data[,i[1]], 2), conc_data[,i[2]])))
如果“ 0”的值必须为零
out <- cbind(conc_data[1], sapply(list(2:3, 4:5), function(i) {
dat <- conc_data[i]
i1 <- !rowSums(dat != 0)
v1 <- do.call(sprintf, c(fmt = "%d(%.3f)", dat))
v1[i1] <- 0
v1
}))
names(out)[-1] <- names(conc_data)[c(2, 4)]
out
# kod_nar.id x123_1 x125_3
#1 1 0 0
#2 3 0(0.123) 1(0.234)
#3 2 0(0.122) 2(0.990)
或更紧凑
data.frame(c(conc_data[1], Map(sprintf, conc_data[c(2, 4)],
conc_data[c(3, 5)], MoreArgs = list(fmt = "%d(%.3f)"))))
答案 1 :(得分:4)
或者:
conc_data$x123_1 <- with(conc_data, ifelse(x124_2 == 0, "0", sprintf("%d(%.3f)", x123_1, x124_2)))
conc_data$x125_3 <- with(conc_data, ifelse(x126_4 == 0, "0", sprintf("%d(%.3f)", x125_3, x126_4)))
答案 2 :(得分:3)
我们可以使用split.default
拆分每两列,并使用sapply
来paste
将两列以所需的格式合并在一起。我们通过选择链列名称来将名称添加到输出中。
output <- cbind(conc_data[1], sapply(split.default(conc_data[-1],
rep(seq_along(conc_data), each = 2)[1:(ncol(conc_data) - 1)]),
function(x) paste0(x[[1]], "(", x[[2]], ")")))
names(output)[-1] <- names(conc_data)[-1][c(TRUE, FALSE)]
output
# kod_nar.id x123_1 x125_3
#1 1 0(0) 0(0)
#2 3 0(0.123) 1(0.234)
#3 2 0(0.122) 2(0.99)
或者也许更简单一些,使用gl
output <- cbind(conc_data[1], sapply(split.default(conc_data[-1],
gl((ncol(conc_data) - 1)/2, 2)),
function(x) paste0(x[[1]], "(", x[[2]], ")")))
答案 3 :(得分:2)
如果您将其转换为长格式,则可以使用data.table组操作执行此操作,然后将其恢复为宽格式
df_long <-
melt(conc_data, 1)[
, .(variable = variable[1],
value = sprintf('%.0f(%.3f)', value[1], value[2]))
, by = .(kod_nar.id, id = (rowid(kod_nar.id) - 1) %/% 2)]
out <- dcast(df_long, kod_nar.id ~ variable)
out
# kod_nar.id x123_1 x125_3
# 1: 1 0(0.000) 0(0.000)
# 2: 2 0(0.122) 2(0.990)
# 3: 3 0(0.123) 1(0.234)
如果仅在第一行上放置'0'
很重要,则可以添加此额外步骤
out <- out[, lapply(.SD, function(x) ifelse(grepl('[1-9]', x), x, '0'))]
out
# kod_nar.id x123_1 x125_3
# 1: 1 0 0
# 2: 2 0(0.122) 2(0.990)
# 3: 3 0(0.123) 1(0.234)
答案 4 :(得分:1)
这是一个tidyverse
解决方案:
library(tidyverse)
conc_data %>%
mutate(x123_1 = ifelse(x123_1 == x124_2,
x123_1,
paste0(x123_1, "(", x124_2, ")")
),
x125_3 = ifelse(x125_3 == x126_4,
x125_3,
paste0(x125_3, "(", x126_4, ")")
)) %>%
select(x123_1, x125_3)
x123_1 x125_3
1 0 0
2 0(0.123) 1(0.234)
3 0(0.122) 2(0.99)
答案 5 :(得分:1)
您可以执行此操作,例如通过使用sapply
和paste
。我假设如果两列中的数字相等,则仅打印一个数字:
tt <- seq(2,ncol(conc_data),2)
res <- cbind(conc_data[1], sapply(tt, function(i) {
ifelse(conc_data[,i] != conc_data[,i+1], paste0(conc_data[,i], "(", conc_data[,i+1],")") ,paste0(conc_data[,i]))
}
))
names(res)[-1] <- names(conc_data)[s]
res
# kod_nar.id x123_1 x125_3
#1 1 0 0
#2 3 0(0.123) 1(0.234)
#3 2 0(0.122) 2(0.99)
或通过直接在sapply
中使用列名:
tt <- seq(2,ncol(conc_data),2)
cbind(conc_data[1], sapply(names(conc_data)[tt], function(i) {
i2 <- which(names(conc_data) == i)+1
ifelse(conc_data[,i] != conc_data[,i2], paste0(conc_data[,i], "(", conc_data[,i2],")") ,paste0(conc_data[,i]))
}
))
# kod_nar.id x123_1 x125_3
#1 1 0 0
#2 3 0(0.123) 1(0.234)
#3 2 0(0.122) 2(0.99)