如何从数据框中简单地提取许多重复行

时间:2017-10-02 20:11:08

标签: r

如何轻松生成此序列?

c(1,2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,
   2,3,2,4,2,5,2,6,2,7,2,8,2,9,2,10)

有没有简单的方法来写这个?

6 个答案:

答案 0 :(得分:6)

我想你想要像

这样的东西
$cnt=10000;
for($i=0;$i<$cnt;$i++) {
  $array[]['key1'] = 1;
  $array[]['key2'] = 2;
  $array[]['key3'] = 3;
}
/*array_walk($array, function (&$item,$key) {            
   $item['key4'] = 1;
   $item['key5'] = 1;
   $item['key6'] = 1;
}); //memory used PHP7/PHP5: 13 437 720 - 25 924 944 */
/*$map = array_map(function (array $item) {            
   $item['key4'] = 1;
   $item['key5'] = 1;
   $item['key6'] = 1;
   return $item;
}, $array); //memory used PHP7/PHP5: 25 050 360 - 40 850 480*/

作为数据框

t(combn(1:10, 2))

      # [,1] [,2]
 # [1,]    1    2
 # [2,]    1    3
 # [3,]    1    4
 # [4,]    1    5
 # [5,]    1    6
 # [6,]    1    7
 # [7,]    1    8
 # [8,]    1    9
 # [9,]    1   10
# [10,]    2    3
# [11,]    2    4
# [12,]    2    5
# [13,]    2    6
# [14,]    2    7
# [15,]    2    8
# [16,]    2    9
# [17,]    2   10
# etc

答案 1 :(得分:5)

这是部分 - dplyr解决方案。 (当然,使用filter()的替换并且不使用管道是微不足道的......)expand.grid通常适用于此,但在这种情况下,它比CPak使用的更复杂一点combn因为我们必须切换列顺序:

expand.grid(1:10, 1:10) %>% rev %>% filter(Var2 < Var1) %>% t %>% as.vector
 [1]  1  2  1  3  1  4  1  5  1  6  1  7  1  8  1  9  1 10  2  3  2  4  2  5  2  6  2
[28]  7  2  8  2  9  2 10  3  4  3  5  3  6  3  7  3  8  3  9  3 10  4  5  4  6  4  7
[55]  4  8  4  9  4 10  5  6  5  7  5  8  5  9  5 10  6  7  6  8  6  9  6 10  7  8  7
[82]  9  7 10  8  9  8 10  9 10

添加base方法:

n = 10
unlist(lapply(1:(n - 1), FUN = function(x) as.vector(rbind(x, (x + 1):n))))

对于大n,我希望这会快得多,因为它根本不使用数据帧,不会生成不需要的组合,然后将它们过滤掉。

答案 2 :(得分:3)

这是一种base R方式。

fun <- function(x, k) c(k, x)

n <- 10
res <- lapply(seq_len(n - 1), function(k) sapply((k + 1):n, fun, k))
unlist(lapply(res, c))
# [1]  1  2  1  3  1  4  1  5  1  6  1  7  1  8  1  9  1 10  2  3  2  4  2  5  2
#[26]  6  2  7  2  8  2  9  2 10  3  4  3  5  3  6  3  7  3  8  3  9  3 10  4  5
#[51]  4  6  4  7  4  8  4  9  4 10  5  6  5  7  5  8  5  9  5 10  6  7  6  8  6
#[76]  9  6 10  7  8  7  9  7 10  8  9  8 10  9 10

答案 3 :(得分:2)

这是一个使用基数R的小功能,允许您控制起始值和停止值。

combos <- function(x, y) unlist(Map(rbind, as.list(1:x), lapply(2:(x+1), ":", y)))

combos(3, 10)
 [1]  1  2  1  3  1  4  1  5  1  6  1  7  1  8  1  9  1 10  2  3  2  4  2  5  2  6  2
[28]  7  2  8  2  9  2 10  3  4  3  5  3  6  3  7  3  8  3  9  3 10
combos(2, 5)
 [1] 1 2 1 3 1 4 1 5 2 3 2 4 2 5
combos(3, 5)
 [1] 1 2 1 3 1 4 1 5 2 3 2 4 2 5 3 4 3 5

答案 4 :(得分:1)

以下是使用dplyrtidyr的选项。 result是最终输出。您可能希望进一步对result向量进行子集化,或者根据您的需要对df2进行子集化。在看到Gregor的回答之后,我认为我原来的方法过于复杂,因此我更新了方法如下。

library(dplyr)
library(tidyr)

dt <- data.frame(a = 1:10, b = 1:10)

dt2 <- dt %>%
  complete(a, b) %>%
  filter(b > a)

result <- dt2 %>% 
  t() %>%
  as.vector()

result
 [1]  1  2  1  3  1  4  1  5  1  6  1  7  1  8  1  9  1 10  2  3  2  4  2  5  2  6  2
[28]  7  2  8  2  9  2 10  3  4  3  5  3  6  3  7  3  8  3  9  3 10  4  5  4  6  4  7
[55]  4  8  4  9  4 10  5  6  5  7  5  8  5  9  5 10  6  7  6  8  6  9  6 10  7  8  7
[82]  9  7 10  8  9  8 10  9 10

由于行是根据列a排序的,因此您可以根据所需的数量过滤列a。例如,如果您只想要第一个数字不大于2.您可以对df2

执行以下操作
dt2 <- dt %>%
  complete(a, b) %>%
  filter(b > a) %>%
  filter(a < 3)

如上所述,使用df2生成result相同的代码,您将获得与示例相同的所需输出。

答案 5 :(得分:0)

我使用了for循环。如果你想要一个很长的序列,这不是你最好的选择:

# Create vectors for desired sequence
x <- 1:10
y <- 1:2

# Initiate sequence vector
seq <- c()

# Loop to fill in sequence vector
for(elem in y){
  for(i in 1:length(x)){
      toappend <- c(elem, x[i])
      seq <- c(seq, toappend)
    }
  }

> print(seq)
 [1]  1  1  1  2  1  3  1  4  1  5  1  6  1  7  1  8  1  9  1 10  2  1  2  2  2  3  2  4  2
[30]  5  2  6  2  7  2  8  2  9  2 10