首页 > 解决方案 > 具有某些条件的 data.frame 中字符单元格的组合

问题描述

我希望有人可以帮助我解决这个问题。想象以下字符数据框:

df <- data.frame(X1=c("a", "b"), X2=c("k", "l"))

df

  X1 X2
1  a  k
2  b  l

我想获得列的单元格之间的所有可能组合。

在这种情况下:

ak

bk

bl

我的问题是我不想指定我有多少列和行,并且代码应该忽略 NA(缺失值)。编辑:所以在三列中必须有三个元素。

df <- data.frame(X1=c("a", "b", "NA", "NA"), X2=c("k", "l", "m", "NA"), X3=c("e", "t", "l", "p"))

df

  X1 X2 X3
1  a  k  e
2  b  l  t
3 NA  m  l
4 NA NA  p

另一个问题是,我不想要长度小于列数的组合。因此,请确定一些适合的示例:

阿克

麦酒

blt

一些不适合的例子:

呐呐

然后应将结果保存在字符向量中。向量中的每个元素都应该是一个组合。

也许有人有一个想法,或者可能已经有一个线程可以帮助我,但我没有找到一些。

我已经尝试过不同的函数,比如 combn() 或 combine() 但要么它不适合这个问题,要么我以错误的方式使用它。

编辑:第二个df的整个假定输出:

阿克

akt

akl

akp

麦酒

alt

全部

阿尔卑斯山

AME

上午

反洗钱

放大器

bke

bkt

bkl

bkp

布尔

blt

比尔

blp

bme

bmt

bml

bmp

我希望我没有犯错。

标签: rdataframe

解决方案


data.frame 中组合的 R 基函数是expand.grid.

expand.grid(df)
   X1 X2 X3
1   a  k  e
2   b  k  e
3  NA  k  e
4  NA  k  e
... <lines removed for brevity>
61  a NA  p
62  b NA  p
63 NA NA  p
64 NA NA  p

您提供的示例数据的问题是它没有任何NA值。创建 时data.frame,将文本“NA”放在引号中,这告诉 R 中的每一列都df应该包含一个字符向量,其元素等于字母“N”,后跟字母“A”,而不是 R 的缺失值数据,NA (更准确地说,每一列都是一个factor(枚举vector,请参阅 R 帮助中的 ?factor),包括一个级别“NA”(一个字符向量,包含字母“N”后跟字母“A” ) 而不是 的级别NA,但我离题了...查看factorsAsStringsR 帮助中的论点?data.frame-- 以及下面的主题以 ?factors获取更多信息。)

底线:要使用factor包含NA值的列创建 data.frame,请不要在 周围使用引号NA

df_NAs <- data.frame(X1=c("a", "b", NA, NA), X2=c("k", "l", "m", NA), X3=c("e", "t", "l", "p"))

现在,为了解决您的问题,我们需要NAdf_NAs调用expand.grid. 记住 Rdata.frame继承自(list换句话说,R data.frame是一个列表,其中列表的每个元素包含一列向量。结果将作为向量列表返回:data.framelapplydata.framena.omitNA

list_NoNAs <- lapply(df_NAs, na.omit)

list_NoNAs

$X1
[1] a b
attr(,"na.action")
[1] 3 4
attr(,"class")
[1] "omit"
Levels: a b

$X2
[1] k l m
attr(,"na.action")
[1] 4
attr(,"class")
[1] "omit"
Levels: k l m

$X3
[1] e t l p
Levels: e l p t

通过查看列表中每个项目的第一行,您可以看到NAs 已被删除。列表中每个元素的长度可以显示为:

lapply(list_NoNAs, length)

$X1
[1] 2

$X2
[1] 3

$X3
[1] 4

所以现在你有不同长度的 a ,list因为从.vectorsNAdata.frame

幸运的是,expand.grid不仅在data.frames 上运行,而且在lists 上运行;它不关心列表的每个元素是否有不同的长度。

foo = list(
   letters = c("a", "b", "c"),
   numbers = c(1, 2),
   booleans = c(T)
)

expand.grid(foo)

  letters numbers booleans
1       a       1     TRUE
2       b       1     TRUE
3       c       1     TRUE
4       a       2     TRUE
5       b       2     TRUE
6       c       2     TRUE

因此,要生成 adata.frame的组合,NA省略 s:

df_combos <- expand.grid(lapply(df_NAs, na.omit))

df_combos

   X1 X2 X3
1   a  k  e
2   b  k  e
3   a  l  e
4   b  l  e
5   a  m  e
6   b  m  e
7   a  k  t
8   b  k  t
9   a  l  t
10  b  l  t
11  a  m  t
12  b  m  t
13  a  k  l
14  b  k  l
15  a  l  l
16  b  l  l
17  a  m  l
18  b  m  l
19  a  k  p
20  b  k  p
21  a  l  p
22  b  l  p
23  a  m  p
24  b  m  p

现在我们需要从combos. 要从值向量创建单个字符串,您可以使用:

paste(c("a", "b", "c"), collapse = "")

[1] "abc"

因此,要从 的每一行创建一个字符向量df_combos,您可以使用 将 的每一行发送data.framepaste函数apply

apply(combos, 1, paste, collapse = "")

 [1] "ake" "bke" "ale" "ble" "ame" "bme" "akt" "bkt" "alt" "blt" "amt" "bmt" "akl" "bkl" "all" "bll" "aml" "bml" "akp"
[20] "bkp" "alp" "blp" "amp" "bmp"

要在字母之间放置空格,请将collapse参数更改为" ",如下所示:

apply(combos, 1, paste, collapse = " ")

[1] "a k e" "b k e" "a l e" "b l e" "a m e" "b m e" "a k t" "b k t" "a l t" "b l t" "a m t" "b m t" "a k l" "b k l"
[15] "a l l" "b l l" "a m l" "b m l" "a k p" "b k p" "a l p" "b l p" "a m p" "b m p"

如果你真的想在一行完全不可读的代码中完成这一切,这里是:

apply(expand.grid(lapply(df_NAs, na.omit)), 1, paste, collapse = "")

推荐阅读