根据字符串中的成对组合分配组

时间:2017-10-23 22:42:23

标签: r string grouping

我有一个带有以下结构的大df

df <- structure(list(id = c(1, 2, 3, 4, 5, 6, 7), name = c("aa", "ab", "ac",  "aa", "aab", "aac", "aabc")), .Names = c("id", "name"), row.names = c(NA, -7L), class = "data.frame")

df  

   id  name
1  1   aa
2  2   ab
3  3   ac
4  4   aa
5  5   aab
6  6   aac
7  7   aabc

我想根据列名中的两个字符串(此处为aa,ab,ac)创建一个新的列组,以实现类似

的操作
df  

   id  name   group
1  1   aa     1
2  2   ab     2
3  3   ac     3
4  4   aa     1
5  5   aab    1
5  5   aab    2
6  6   aac    1
6  6   aac    3
7  7   aabc   1
7  7   aabc   2
7  7   aabc   3

虽然为两个字符串分配组是直截了当的,但我很难找到一种有效的方法来包含较长​​字符串的成对组合。我想用nchar&gt; 2将每个字符串拆分成所有可能的成对组合,并将它们分配给各自的组但是想知道是否有更好的方法。

补充说明

  1. 仅在df中找到的成对组合(并非所有可能的组合)
  2. 两个字符串的顺序无关紧要(例如ab = ba)
  3. 只有较长字符串的唯一重组(例如,aaab只是aa和ab)d
  4. 没有重组问题的类似问题Assigning groups using grepl with multiple inputs

1 个答案:

答案 0 :(得分:0)

以下

怎么样?
# Your data
df <- structure(
    list(
        id = c(1, 2, 3, 4, 5, 6, 7), 
        name = c("aa", "ab", "ac",  "aa", "aab", "aac", "aabc")), 
    .Names = c("id", "name"), row.names = c(NA, -7L), class = "data.frame")

# Create all possible 2char combinations from unique chars in string
group <- lapply(strsplit(df$name, ""), function(x) 
    unique(apply(combn(x, 2), 2, function(y) paste0(y, collapse = ""))));

# Melt and add original data
require(reshape2);
df2 <- melt(group);
df2 <- cbind.data.frame(
    df2, 
    df[match(df2$L1, df$id), ]);
df2$group <- as.numeric(as.factor(df2$value));
df2;
#    value L1 id name group
#1      aa  1  1   aa     1
#2      ab  2  2   ab     2
#3      ac  3  3   ac     3
#4      aa  4  4   aa     1
#5      aa  5  5  aab     1
#5.1    ab  5  5  aab     2
#6      aa  6  6  aac     1
#6.1    ac  6  6  aac     3
#7      aa  7  7 aabc     1
#7.1    ab  7  7 aabc     2
#7.2    ac  7  7 aabc     3
#7.3    bc  7  7 aabc     4

说明:strsplit将字符串从df$name拆分为char矢量。 combn根据这些char向量创建所有2-char组合。 paste0unique保留了连接的唯一2-char组合。

请注意,此几乎会重现您的示例。这是因为在我的情况下,aabc也会产生群组4 = bc

更新1

您可以根据2-char比较列表过滤条目

# Filter entries
filter <- c("aa", "ab", "ac");
df2 <- df2[df2$value %in% filter, ]

# Clean up df2 to be consistent with OPs request
df2 <- df2[, -(1:2)];
df2;
#    id name group
#1    1   aa     1
#2    2   ab     2
#3    3   ac     3
#4    4   aa     1
#5    5  aab     1
#5.1  5  aab     2
#6    6  aac     1
#6.1  6  aac     3
#7    7 aabc     1
#7.1  7 aabc     2
#7.2  7 aabc     3

更新2

您还可以动态创建过滤器,方法是选择原始value中表示为2-char字符串的dataframe条目(在本例中为aa,{{1} }和ab)。

ac