【问题标题】:Making non-unique row names unique使非唯一的行名唯一
【发布时间】:2018-03-20 10:23:45
【问题描述】:

我在 R 中有一个 data.frame 对象,我想为其设置非唯一的行名:

38.40000 41.75200 44.38400 44.18400 45.37600 37.49600 41.36800 33.93600 38.00800  42.51200 46.49600  40.48000  45.40800  46.32800  43.78400  39.88800  38.84000  40.56800  42.03200 38.89185
45.53846 50.08462 39.91538 36.95385 34.96154 39.74615 38.01538 35.75385 35.54615  36.69231 35.20769  38.05385  39.29231  37.96923  37.30000  36.86923  39.19231  38.81538  43.69231 38.06400 
46.05176 41.69412 38.80000 37.75529 39.67529 39.07765 39.17647 38.24941 39.58588  38.63529 38.30588  41.87765  38.97412  40.13647  42.27294  38.24471  35.41647  40.80000  38.07059 42.11294
44.20000 43.42857 44.80000 35.20000 35.91429 37.82857 51.45714 44.68571 46.68571  48.74286 41.25091  39.45455  38.17091  40.70182  40.39273  41.28727  40.63636  41.50909  41.68364 41.29455
45.06909 41.09818 40.02909 42.50182 42.34909 39.84727 41.42909 40.47273 40.28000  40.51636 41.25091  39.45455  38.17091  40.70182  40.39273  41.28727  40.63636  41.50909  41.68364 41.29455
40.87407 39.27704 44.13630 43.25037 35.86667 37.30667 38.76148 40.74667 38.93333  43.16148 37.47259  37.73630  38.34370  39.00148  36.96889  37.76593  39.14667  37.92593  37.62963 38.89185

我想要这个虚拟数据的行名是B,C,C,B,E2,E3。但是,我知道 R 不允许非唯一的行名。我的完整数据集A,B,C,D,E1,E2,E3 有七个可能的行名类。

我试图在 R 中编写一个脚本(但失败了),它采用我的非唯一行名的向量,并将数字添加到元素 1、2、3... 等等,具体取决于向量中的那个字符。

因此对于这个虚拟数据,我的向量是B-1,C-1,C-2,B-2,E2-1,E3-1,我的最终矩阵是:

B-1  38.40000 41.75200 44.38400 44.18400 45.37600 37.49600 41.36800 33.93600 38.00800  42.51200 46.49600  40.48000  45.40800  46.32800  43.78400  39.88800  38.84000  40.56800  42.03200 38.89185
C-1  45.53846 50.08462 39.91538 36.95385 34.96154 39.74615 38.01538 35.75385 35.54615  36.69231 35.20769  38.05385  39.29231  37.96923  37.30000  36.86923  39.19231  38.81538  43.69231 38.06400 
C-2  46.05176 41.69412 38.80000 37.75529 39.67529 39.07765 39.17647 38.24941 39.58588  38.63529 38.30588  41.87765  38.97412  40.13647  42.27294  38.24471  35.41647  40.80000  38.07059 42.11294
B-2  44.20000 43.42857 44.80000 35.20000 35.91429 37.82857 51.45714 44.68571 46.68571  48.74286 41.25091  39.45455  38.17091  40.70182  40.39273  41.28727  40.63636  41.50909  41.68364 41.29455
E2-1 45.06909 41.09818 40.02909 42.50182 42.34909 39.84727 41.42909 40.47273 40.28000  40.51636 41.25091  39.45455  38.17091  40.70182  40.39273  41.28727  40.63636  41.50909  41.68364 41.29455
E3-1 40.87407 39.27704 44.13630 43.25037 35.86667 37.30667 38.76148 40.74667 38.93333  43.16148 37.47259  37.73630  38.34370  39.00148  36.96889  37.76593  39.14667  37.92593  37.62963 38.89185

【问题讨论】:

  • 拥有行名重要吗?如果您想将名称用于任何事情,通常将它们放在列中比将它们作为名称更容易。
  • 是的,我愿意。因为我想将这个 data.frame 对象用于 PCA,并通过标签可视化聚类,这只能通过行名实现。
  • 在可视化时只需传递名称向量(PCA 步骤不需要名称)。或者使用矩阵代替数据框:foo <- matrix(nrow = 2); rownames(foo) <- rep("A", 2).
  • 我宁愿有这样的行名,这样更容易。
  • 那么矩阵就是你的选择,不要让你的代码过于复杂,无法像 PCA 这样简单的步骤。

标签: r


【解决方案1】:

如果您真的想要这样做,那么这将起作用

uniqify_names <- function(names_vector) {
    names <- unique(names_vector)
    count_table <- rep(0, length(names))
    names(count_table) <- names # works because R has weird symbol lookup
    update_name <- function(name) {
        new_name <- paste0(name, ".", count_table[name])
        count_table[name] <<- count_table[name] + 1
        new_name
    }
    vapply(names_vector, update_name, FUN.VALUE = "character")
}

它是这样工作的:

> non_unique_names <- c("A", "B", "A", "A", "B", "C", "A", "B", "C")
> uniqify_names(non_unique_names)
    A     B     A     A     B     C     A     B     C 
"A.0" "B.0" "A.1" "A.2" "B.1" "C.0" "A.3" "B.2" "C.1" 

您可以使用此向量中的rownames 设置行名称。

【讨论】:

  • 如果要 1-index,请更改计数表。如果您想使用- 而不是.,请更新paste0 调用。
【解决方案2】:

既然这个问题是怎么做的:

获取非唯一行名的向量并将数字添加到元素 1、2、3

我将忽略 PCA 部分(建议使用矩阵或根本不使用行名)。

要生成想要的名称向量,您可以使用:

foo <- c("A", "B", "C", "C", "B", "E", "E")
paste0(foo, "-", sapply(seq_along(foo), function(x) sum(foo[1:x] == foo[x])))
[1] "A-1" "B-1" "C-1" "C-2" "B-2" "E-1" "E-2"

【讨论】:

  • 感谢您的回答!我们可以把这个讨论聊聊,以获得 PCA 推荐吗?
【解决方案3】:

你可以试试这个。

df <- data.frame(row_name = c('B','C','C','B','E2','E3'))

library(dplyr)

df <- df %>% 
  group_by(row_name) %>% 
  mutate(count = sequence(n()),
         unique_row_name = paste(row_name, count, sep="-"))

df$unique_row_name是你的候选人!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    相关资源
    最近更新 更多