我希望有人可以帮助我解决这个问题。 想象一下以下字符数据框:
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
我希望我没弄错。
答案 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}}),我们可以使用list
将data.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
因此,现在您有NA
个lapply(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。