【问题标题】:how to count and remove similar strings across columns如何计算和删除列中的相似字符串
【发布时间】:2017-07-29 18:11:11
【问题描述】:

我有一个包含许多列的数据。例如这是三列

df<-structure(list(V1 = structure(c(5L, 1L, 7L, 3L, 2L, 4L, 6L, 6L
), .Label = c("CPSIAAAIAAVNALHGR", "DLNYCFSGMSDHR", "FPEHELIVDPQR", 
"IADPDAVKPDDWDEDAPSK", "LWADHGVQACFGR", "WGEAGAEYVVESTGVFTTMEK", 
"YYVTIIDAPGHR"), class = "factor"), V2 = structure(c(5L, 2L, 
7L, 3L, 4L, 6L, 1L, 1L), .Label = c("", "CPSIAAAIAAVNALHGR", 
"GCITIIGGGDTATCCAK", "HVGPGVLSMANAGPNTNGSQFFICTIK", "LLELGPKPEVAQQTR", 
"MVCCSAWSEDHPICNLFTCGFDR", "YYVTIIDAPGHR"), class = "factor"), 
    V3 = structure(c(4L, 3L, 2L, 4L, 3L, 1L, 1L, 1L), .Label = c("", 
    "AVCMLSNTTAIAEAWAR", "DLNYCFSGMSDHR", "FPEHELIVDPQR"), class = "factor")), .Names = c("V1", 
"V2", "V3"), class = "data.frame", row.names = c(NA, -8L))

-第一列,我们不看其他列,我们只计算有多少个字符串并保持唯一的一个

  • 第二列,我们保留唯一的,并且我们删除那些已经在第一列中的那些

  • 第三列,我们保持唯一,并删除第一列和第二列中的字符串

这将持续到我们拥有的尽可能多的列

例如对于这个数据,我们将有以下

 Column 1              Column 2                    Column 3
LWADHGVQACFGR
CPSIAAAIAAVNALHGR     LLELGPKPEVAQQTR              AVCMLSNTTAIAEAWAR
YYVTIIDAPGHR          GCITIIGGGDTATCCAK 
FPEHELIVDPQR          HVGPGVLSMANAGPNTNGSQFFICTIK   
DLNYCFSGMSDHR         MVCCSAWSEDHPICNLFTCGFDR   
IADPDAVKPDDWDEDAPSK     
WGEAGAEYVVESTGVFTTMEK   

【问题讨论】:

  • 对不起,我一定是看错了问题
  • @akrun 如果您知道任何解决方案,我将很乐意接受它
  • 我现在有点忙,有一些模型正在运行
  • 你确定你的结果是正确的并反映了你的例子吗?
  • @Sotos 是的,我认为结果是正确的

标签: r string dataframe


【解决方案1】:

这是tidyverse的解决方案,

library(tidyverse)

df1 <- df %>% 
 gather(var, string) %>% 
 filter(string != '' & !duplicated(string)) %>% 
 group_by(var) %>% 
 mutate(cnt = seq(n())) %>% 
 spread(var, string) %>%
 select(-cnt)

这给了

# A tibble: 7 x 4
    cnt                    V1                          V2                V3
* <int>                 <chr>                       <chr>             <chr>
1     1         LWADHGVQACFGR             LLELGPKPEVAQQTR AVCMLSNTTAIAEAWAR
2     2     CPSIAAAIAAVNALHGR           GCITIIGGGDTATCCAK              <NA>
3     3          YYVTIIDAPGHR HVGPGVLSMANAGPNTNGSQFFICTIK              <NA>
4     4          FPEHELIVDPQR     MVCCSAWSEDHPICNLFTCGFDR              <NA>
5     5         DLNYCFSGMSDHR                        <NA>              <NA>
6     6   IADPDAVKPDDWDEDAPSK                        <NA>              <NA>
7     7 WGEAGAEYVVESTGVFTTMEK                        <NA>              <NA>

可以使用colSums获取字符串的个数,

colSums(!is.na(df1))
#V1 V2 V3 
# 7  4  1 

通过 base R 的类似方法,将字符串保存在列表中,

df[] <- lapply(df, as.character)
d1 <- stack(df)
d1 <- d1[d1$values != '' & !duplicated(d1$values),]
l1 <- unstack(d1, values ~ ind)

lengths(l1)
#V1 V2 V3 
# 7  4  1

【讨论】:

  • 你可以在每列的顶部添加每列的字符串数而不是 吗?
  • 什么意思? 就是数据框在控制台中的显示方式。您的意思是在顶部添加另一行字符串数(7、4、1)?
  • 我收到了这个错误Error in select(-cnt) : object 'cnt' not found
  • 我的小错字。再试一次
  • 另外两个请求。 1-您能否添加一些解释,以便我了解您的所作所为? 2-当我这样做colSums(!is.na(df1))时,它会使列随机报告,我怎样才能以与它们相同的顺序打印列(如lengths(l1)
【解决方案2】:

基础 R 解决方案。 df2 是最终输出。

# Convert to character
L1 <- lapply(df, as.character)
# Get unique string
L2 <- lapply(L1, unique)
# Remove ""
L3 <- lapply(L2, function(vec){vec <- vec[!(vec %in% "")]})

# Use for loop to remove non-unique string from previous columns
for (i in 2:length(L3)){
  previous_vec <- unlist(L3[1:(i - 1)])
  current_vec <- L3[[i]]
  L3[[i]] <- current_vec[!(current_vec %in% previous_vec)]
}

# Get the maximum column length
max_num <- max(sapply(L3, length))

# Append "" to each column
L4 <- lapply(L3, function(vec){vec <- c(vec, rep("", max_num - length(vec)))})

# Convert L4 to a data frame
df2 <- as.data.frame(do.call(cbind, L4))

【讨论】:

  • 我喜欢你的回答
猜你喜欢
  • 2017-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
相关资源
最近更新 更多