具有某些条件的data.frame中字符单元的组合

时间:2019-07-28 11:10:23

标签: r dataframe

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

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

df

  X1 X2
1  a  k
2  b  l

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

在这种情况下:

一个

a

b k

b l

我的问题是我不想指定我有多少列和行,并且代码应该忽略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

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

知道

所有

b l t

一些不适合的示例:

a

NA NA p

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

也许有人有一个主意,或者也许已经有一个线索可以帮助我,但我没有找到一些线索。

我尝试了不同的功能,例如 combn()或Combines(),但它要么不适合该问题,要么我以错误的方式使用了它。

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

知道

一千吨

一个

一个k

所有

所有

所有

a l p

一米

一米

a m p

b k e

b k t

b k l

b k p

b

b l t

b l l

b l p

b m e

b m t

b m l

b m p

我希望我没弄错。

2 个答案:

答案 0 :(得分:0)

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”,后跟字母对于缺失数据,NA是A而不是R值(更精确地说,每一列都是factor(枚举的vector,请参见R帮助中的?factor)包含级别“ NA”(包含字母“ N”后跟字母“ A”的字符向量),而不是NA的级别,但是我离题了……签出{{1} } R帮助中的参数-factorsAsStrings-和?data.frame下的主题以获取更多信息。)

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

NA

现在,要解决您的问题,我们需要在调用df_NAs <- data.frame(X1=c("a", "b", NA, NA), X2=c("k", "l", "m", NA), X3=c("e", "t", "l", "p")) 之前从NA的每一列中删除df_NAs。请记住,R expand.grid是从data.frame继承的(换句话说,R data.frame 是一个列表,其中列表的每个元素都包含{{ 1}}),我们可以使用listdata.frame的每一列传递到lapply,R函数从向量中剥离data.frame。结果将作为向量列表返回:

na.omit

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

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

因此,现在您有NAlapply(list_NoNAs, length) $X1 [1] 2 $X2 [1] 3 $X3 [1] 4 ,它们的长度是不同的,因为从list的每一列中删除了不同数量的vectors

幸运的是,NA不仅在data.frame上运行,而且还在expand.grid上运行;不管列表中每个元素的长度是否不同。

data.frame

因此,要生成list个组合,并省略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

data.frame

现在,我们需要从NA的每一行生成一个字符串。要从值向量创建单个字符串,可以使用:

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.frame函数:

paste

要在字母之间放置空格,请将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

如果您真的想在一行代码中完成全部操作(这是完全不可读的),则为:

" "

答案 1 :(得分:0)

另一种解决方案:

> df <- data.frame(X1 = c("a", "b", "NA", "NA"), X2 = c("k", "l", "m", "NA"), X3 = c("e", "t", "l", "p"), stringsAsFactors = FALSE)
> df[df == "NA"] <- NA
> na.omit(object = rev(x = expand.grid(rev(x = df))))
   X1 X2 X3
1   a  k  e
2   a  k  t
3   a  k  l
4   a  k  p
5   a  l  e
6   a  l  t
7   a  l  l
8   a  l  p
9   a  m  e
10  a  m  t
11  a  m  l
12  a  m  p
17  b  k  e
18  b  k  t
19  b  k  l
20  b  k  p
21  b  l  e
22  b  l  t
23  b  l  l
24  b  l  p
25  b  m  e
26  b  m  t
27  b  m  l
28  b  m  p

如果需要字符向量,则可以使用paste,如建议的@Geoffrey Poole。