希望这不是重复——我已经进行了搜索,但找不到我要找的东西。
我在 R 中有一个数据框(df)
1 2 3 4 5
1 1 0.5 0.5 0 1
2 0.5 0.5 0.5 0 1
3 1 1 0 0 1
4 1 1 0 0 1
5 1 1 0 0 1
(其中1-5表示行名和列名)
我想将列名称粘贴到每个单元格,并用“:”分隔,使其看起来像这样:
1 2 3 4 5
1 1:1 2:0.5 3:0.5 4:0 5:1
2 1:0.5 2:0.5 3:0.5 4:0 5:1
3 1:1 2:1 3:0 4:0 5:1
4 1:1 2:1 3:0 4:0 5:1
5 1:1 2:1 3:0 4:0 5:1
但是,我的实际数据要大一些。
我目前有
apply(df, 2, function(x) paste(colnames(df)[x], x, sep=":"))
当然这不起作用,因为 colnames(df)[x] 没有任何意义。 我可以在第一个“粘贴”术语中添加任何内容来进行排序吗?或者其他功能可以做得更好?
谢谢。
为了解释我的评论,
Map
是lapply
的多元版本,所以
df <- data.frame(`1` = c(1, 0.5, 1, 1, 1),
`2` = c(0.5, 0.5, 1, 1, 1),
`3` = c(0.5, 0.5, 0, 0, 0),
`4` = c(0L, 0L, 0L, 0L, 0L),
`5` = c(1L, 1L, 1L, 1L, 1L),
check.names = FALSE)
df[] <- Map(paste, names(df), df, sep = ':')
df
## 1 2 3 4 5
## 1 1:1 2:0.5 3:0.5 4:0 5:1
## 2 1:0.5 2:0.5 3:0.5 4:0 5:1
## 3 1:1 2:1 3:0 4:0 5:1
## 4 1:1 2:1 3:0 4:0 5:1
## 5 1:1 2:1 3:0 4:0 5:1
这里
Map
取 names(df)
的第一个元素,即 1
,并将 paste
设为 df
的第一个元素,即第一列。分配给 df[]
会保留列表的 data.frame 类,从而保留原始结构。
如果您的数据是矩阵,您可以使用
sweep
做同样的事情:
mat <- matrix(c(1, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1),
5, 5,
dimnames = list(c("1", "2", "3", "4", "5"),
c("1", "2", "3", "4", "5")))
mat[] <- sweep(mat, 2, colnames(df), function(x, y) paste(y, x, sep = ':'))
mat
## 1 2 3 4 5
## 1 "1:1" "2:0.5" "3:0.5" "4:0" "5:1"
## 2 "1:0.5" "2:0.5" "3:0.5" "4:0" "5:1"
## 3 "1:1" "2:1" "3:0" "4:0" "5:1"
## 4 "1:1" "2:1" "3:0" "4:0" "5:1"
## 5 "1:1" "2:1" "3:0" "4:0" "5:1"
作为循环的替代方法,您可以使用
col(., as.factor = TRUE)
创建列名矩阵,然后将其粘贴到数据中(强制为矩阵)。
df[] <- paste(col(df, TRUE), as.matrix(df), sep = ":")
结果:
1 2 3 4 5 1 1:1 2:0.5 3:0.5 4:0 5:1 2 1:0.5 2:0.5 3:0.5 4:0 5:1 3 1:1 2:1 3:0 4:0 5:1 4 1:1 2:1 3:0 4:0 5:1 5 1:1 2:1 3:0 4:0 5:1
实际上,对于这些特定的列名称,
as.factor = TRUE
是不必要的。 但列名必须与列号不同。 对于这个特定的例子,它可能是
df[] <- paste(col(df), as.matrix(df), sep = ":")
附注您确实应该使用包含 100% 数字数据的矩阵,而不是数据框。
数据:
df <- structure(list(`1` = c(1, 0.5, 1, 1, 1), `2` = c(0.5, 0.5, 1,
1, 1), `3` = c(0.5, 0.5, 0, 0, 0), `4` = c(0L, 0L, 0L, 0L, 0L
), `5` = c(1L, 1L, 1L, 1L, 1L)), .Names = c("1", "2", "3", "4",
"5"), class = "data.frame", row.names = c("1", "2", "3", "4",
"5"))
我们可以
unlist
数据集和paste
使用列名称的复制元素
df[] <- paste(names(df)[col(df)], unlist(df), sep=":")
df
# 1 2 3 4 5
#1 1:1 2:0.5 3:0.5 4:0 5:1
#2 1:0.5 2:0.5 3:0.5 4:0 5:1
#3 1:1 2:1 3:0 4:0 5:1
#4 1:1 2:1 3:0 4:0 5:1
#5 1:1 2:1 3:0 4:0 5:1
df <- structure(list(`1` = c(1, 0.5, 1, 1, 1), `2` = c(0.5, 0.5, 1,
1, 1), `3` = c(0.5, 0.5, 0, 0, 0), `4` = c(0L, 0L, 0L, 0L, 0L
), `5` = c(1L, 1L, 1L, 1L, 1L)), .Names = c("1", "2", "3", "4",
"5"), class = "data.frame", row.names = c("1", "2", "3", "4",
"5"))
要更新 tidyverse,您现在可以运行
df <- map2_dfc(colnames(df), df, paste, sep = ':')
map2
需要 2 个输入用于粘贴功能,并且 _dfc
标签返回数据帧作为结果而不是列表。
与
cur_column()
dt <- data.frame(1 = c(1, 0.5, 1, 1, 1),
2 = c(0.5, 0.5, 1, 1, 1),
3 = c(0.5, 0.5, 0, 0, 0),
4 = c(0L, 0L, 0L, 0L, 0L),
5 = c(1L, 1L, 1L, 1L, 1L),
check.names = FALSE)
dt %>%
mutate(across(everything(), ~paste(cur_column(), ., sep = ":")))