如何使这个代码在R中更有效?

时间:2018-03-21 18:12:53

标签: r performance dataframe matrix

我知道这是一个愚蠢的问题,但我对我的代码感到沮丧,因为它花了很多时间。 Jere是我的代码的一部分。 基本上我有一个名为"距离" ...

的矩阵
   a  b  c  
1  2  5  7
2  6  8  4
3  9  2  3

然后假设我在数据框中有一列,包含{a,b,c}

c1  c2  c3
c  ...  ...
a
a  just another column
b
c ... ...

所以我想做一个匹配,我想用ncol = nrow(距离)和nrow = nrow(c1)制作另一个矩阵。用它们的距离值替换因子值。这是我要制作的第一列矩阵的例子

a will replaced by 2 
b will replaced by 5
c will replaced by 7

对于第二列,我将从距离矩阵中取第2行,依此类推......所以结果将是这样的

m1  m2  m3
7   4   3
2   6   9
2   6   9
5   8   2
7   4   3

这只是一个简单的示例,我正在运行此代码,但是当它处理大量迭代时,它对我来说有点紧张。

for(l in 1:ncol(d.cat)){
  get.unique = sort(unique(d.cat[, l]))
  for(j in 1:nrow(d.cat)){
    value = as.character(d.cat[j, l])
    index = which(get.unique == value)
    d2[j,l] = (d[[l]][i, index])
  }
}

d.cat是分类数据。 d [[...]]是d.cat中每列的矩阵距离列表。

4 个答案:

答案 0 :(得分:2)

尝试存储索引并一次性进行更新。假设你的距离矩阵是dmat,数据帧是df,你想创建一个名为newmat

的矩阵
a.ind = which(df$c1=="a")
b.ind = which(df$c1=="b")
c.ind = which(df$c1=="c")
newmat = matrix(0,nrow=length(df$c1),ncol=3)
newmat[a.ind,] = dmat[,1]
newmat[b.ind,] = dmat[,2]
newmat[c.ind,] = dmat[,3]

答案 1 :(得分:1)

您的数据

mat <- matrix(c(2,6,9,5,8,2,7,4,3), nrow=3)
rownames(mat) <- 1:3
colnames(mat) <- letters[1:3]

library(dplyr)
set.seed(1)
df <- as.data.frame(matrix(sample(letters[1:3], 12, replace=TRUE), nrow=4)) %>%
        setNames(paste0("c", 1:3))

  # c1 c2 c3
# 1  a  a  b
# 2  b  c  a
# 3  b  c  a
# 4  c  b  a

使用purrr::map2_df,遍历df列和tmat

library(purrr)
tmat <- t(mat)
map2_df(df, seq_len(ncol(tmat)), ~tmat[,.y][.x])

# # A tibble: 4 x 3
     # c1    c2    c3
  # <dbl> <dbl> <dbl>
# 1    2.    6.    2.
# 2    5.    4.    9.
# 3    5.    4.    9.
# 4    7.    8.    9.

答案 2 :(得分:1)

以下是我尝试使用tidyverse:

library(tidyverse)

# Lets create some example
distance <- data_frame(a = sample(1:10, 1000, T), b = sample(1:10, 1000, T), c = sample(1:10, 1000, T))
c1 <- data_frame(c1 = sample(letters[1:3], 1000, T), c2 = sample(letters[1:3], 1000, T))

# First rearrange a little bit your data to make it more tidy
distance2 <- distance %>% 
  mutate(i = seq_len(n())) %>% 
  gather(col, value, -i)
c2 <- c1 %>% 
  mutate(i = seq_len(n()) %>%
  gather(col, value, -i)

# Now just join the data and spread it again
c12 %>% 
  left_join(distance2, by = c("i", "value" = "col")) %>% 
  select(i, col, value.y) %>% 
  spread(col, value.y)

答案 3 :(得分:1)

这是一些数据

set.seed(123)
d = matrix(1:9, 3, dimnames=list(NULL, letters[1:3]))
df = data.frame(c1 = sample(letters[1:3], 10, TRUE), stringsAsFactors=FALSE)

和解决方案

t(d[, match(df$c1, colnames(d))])

例如

> d
     a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> df$c1
 [1] "a" "c" "b" "c" "c" "a" "b" "c" "b" "b"
> t(d[,match(df$c1, colnames(d))])
  [,1] [,2] [,3]
a    1    2    3
c    7    8    9
b    4    5    6
c    7    8    9
c    7    8    9
a    1    2    3
b    4    5    6
c    7    8    9
b    4    5    6
b    4    5    6