特定条件下字母/数字的所有组合

Chr*_*ano 6 for-loop r dataframe

我创建了这些向量:

Letters <- c("A","C","E","G","H","J","K")  
Numbers <- c(0,1,2,3,4,6,7,9) 
AlphaNumeric <- c(Letters, Numbers)
Run Code Online (Sandbox Code Playgroud)

我想在以下三个条件下使用上面提到的所有元素接收所有3元素组合(例如AA1,G26等)的数据帧:

1.)第一个元素是一封信

2.)第二个元素是数字或SAME字母作为第一个元素

3.)第三个元素是一个数字

方法:我尝试使用expand.grid()并成功设法获得3个元素的所有组合.然后我尝试expand.grid(x = Letters, y = AlphaNumeric, z = Numbers)并设法实现1.)和3.)但到目前为止未能管理2.).

不满意的解决方案:我已经找到了一种使用for循环执行此操作的方法,但我想除此之外必须有一种更简单的方法:

   LNN <- expand.grid(x = Letters, y = Numbers, z = Numbers)

   for ( Element in Letters) {
       currentLLN <- expand.grid(x = Element, y = Element, z = Numbers)
       LNN <- merge(LNN, currentLLN, all = TRUE)}
Run Code Online (Sandbox Code Playgroud)

非常感谢任何帮助,谢谢你,Christian

Flo*_*ian 6

您可以创建两个数据帧,一个是第二个元素是数字,另一个是第二个元素与第一个元素相同,然后rbind是那些.下面给出一个示例,请注意我为了说明目的限制了您的示例数据.

Letters <- LETTERS[1:3]  
Numbers <- c(1,2)

df1 = expand.grid(v1=Letters,v3=Numbers,stringsAsFactors = F)
df1$v2 = df1$v1
df1 = df1[,c('v1','v2','v3')]
df2 = expand.grid(v1=Letters,v2=as.character(Numbers),v3=Numbers, stringsAsFactors = F)
df = rbind(df1,df2)
Run Code Online (Sandbox Code Playgroud)

输出:

> df
   v1 v2 v3
1   A  A  1
2   B  B  1
3   C  C  1
4   A  A  2
5   B  B  2
6   C  C  2
7   A  1  1
8   B  1  1
9   C  1  1
10  A  2  1
11  B  2  1
12  C  2  1
13  A  1  2
14  B  1  2
15  C  1  2
16  A  2  2
17  B  2  2
18  C  2  2
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!


虽然两个答案都运行得非常快,但Parfait的解决方案是解决问题的一个很好的解决方案,我当然不想诋毁他的答案,我认为指出创建额外的组合和子集将成为一个更大的问题,当你的数据是大.基准测试如下所示.

Letters <- c(LETTERS[1:26],letters[1:4])
Numbers <- seq(30)
AlphaNumeric <- c(Letters, Numbers)


f_flo <- function()
{
  df1 = expand.grid(v1=Letters,v3=Numbers,stringsAsFactors = F)
  df1$v2 = df1$v1
  df1 = df1[,c('v1','v2','v3')]
  df2 = expand.grid(v1=Letters,v2=as.character(Numbers),v3=Numbers, stringsAsFactors = F)
  df = rbind(df1,df2)
}

f_parfait <- function()
{
  df <- expand.grid(x = Letters, y = AlphaNumeric, z = Numbers, stringsAsFactors = FALSE)
  sub <- subset(df,  (x == y | grepl("[0-9]", y)) &  grepl("[0-9]", z) )
  sub <- with(sub, sub[order(x, y, z),])   # SORT DATAFRAME
  rownames(sub) <- NULL                    # RESET ROWNAMES
}

library(dplyr)
one_letter <- function(l) {
  expand.grid(l, c(l, Numbers), Numbers, stringsAsFactors = FALSE)
}

f_stibu <- function(){
  df <- bind_rows(lapply(Letters, one_letter))
}


library(microbenchmark)
library(ggplot2)

run_times = microbenchmark(f_flo(),f_parfait(),f_stibu())
autoplot(run_times)
Run Code Online (Sandbox Code Playgroud)

结果:

Unit: milliseconds
        expr        min         lq       mean     median         uq       max neval cld
     f_flo()   1.900719   2.047591   3.666935   2.314258   3.922053  78.74793   100  a 
 f_parfait() 138.028364 142.529904 152.876116 144.159444 146.835958 246.92318   100   b
   f_stibu()   4.130464   4.333130   5.169664   4.585028   6.209233  10.23139   100  a 
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 谢谢@Parfait,我试着拿出字母表的前30个大写字母.我想知道NA的来源,哈哈.我更新了基准. (2认同)

Par*_*ait 4

只需expand.grid()通过grepl调用对数据框进行子集化即可:

df <- expand.grid(x = Letters, y = AlphaNumeric, z = Numbers, stringsAsFactors = FALSE)

sub <- subset(df,  (x == y | grepl("[0-9]", y)) )

sub <- with(sub, sub[order(x, y, z),])   # SORT DATAFRAME
rownames(sub) <- NULL                    # RESET ROWNAMES

head(sub, 10)    
#    x y z
# 1  A 0 0
# 2  A 0 1
# 3  A 0 2
# 4  A 0 3
# 5  A 0 4
# 6  A 0 6
# 7  A 0 7
# 8  A 0 9
# 9  A 1 0
Run Code Online (Sandbox Code Playgroud)