【问题标题】:Automate columns merging where merged values are separated with a delimiter in the container自动合并列,合并值在容器中用分隔符分隔
【发布时间】:2020-08-30 04:35:55
【问题描述】:

我有一个大数据框,其中很多列的列名都包含.。这是我在下面示例中的方法:

#this somewhat resembles what we have in hand
df <- data.frame(id= c("HD1", "HD2", "HD3", "HD4"),
                 mon.1= c(1, 0, 1, 4),
                 mon.2= c("a", "b", "c", "d"),
                 mon.2.4.1...1= c("#ji", "#ki", NA, "#ui"),
                 tue.6= c("1", "2", "3", "4"),
                 tue= c(190, 2345, 41, 89),
                 heh= c("1mn", "2a", "g78", "asd324"),
                 wed= c(1890, 9002, 14341, 657),
                 wed.01= c(NA, "@ksdf", NA, NA),
                 thu.0234= c("@jksdff", "@sfd", "@kukg.676", "@jdkfjk"),
                 rating= c(1,2,3,4))

#in order to collapse the columns, we can apply a mapply variant

#here i attach a new column to original df named combined1 which collapses all mon.....
df<- within(df, 
       combined1 <- Map(list, as.character(mon.1),
                        as.character(mon.2),
                        as.character(mon.2.4.1...1)))

#process repeats for others
df <- within(df,
         combined2 <- Map(list, as.character(tue.6),
                        as.character(tue)))

df <- within(df,
        combined3 <- Map(list, as.character(wed),
                        as.character(wed.01)))

产生以逗号分隔的列 Combined1, Combined2,Combined3

# A tibble: 4 x 14
  id    mon.1 mon.2 mon.2.4.1...1 tue.6   tue heh     wed wed.01 thu.0234 rating
  <fct> <dbl> <fct> <fct>         <fct> <dbl> <fct> <dbl> <fct>  <fct>     <dbl>
1 HD1       1 a     #ji           1       190 1mn    1890 NA     @jksdff       1
2 HD2       0 b     #ki           2      2345 2a     9002 @ksdf  @sfd          2
3 HD3       1 c     NA            3        41 g78   14341 NA     @kukg.6~      3
4 HD4       4 d     #ui           4        89 asd3~   657 NA     @jdkfjk       4
# ... with 3 more variables: combined1 <named list>, combined2 <named list>,
#   combined3 <named list>

我的问题是 montuewed 大约有 20-30 列,我在创建一个可以读取所有内容的方法时遇到问题,例如 wedwed1.43654wed.46 等等。这样我就不必手动输入它们了。感谢您的帮助!

编辑 像这样的

> df[,11:14]
  rating combined1 combined2   combined3
1      1 1, a, #ji    1, 190    1890, NA
2      2 0, b, #ki   2, 2345 9002, @ksdf
3      3  1, c, NA     3, 41   14341, NA
4      4 4, d, #ui     4, 89     657, NA

【问题讨论】:

  • 您的预期输出是什么。你想简单地创建一个list 列吗?
  • 嗨@akrun,预期输出类似于上面(值向量也很好),但我不必手动插入所有wedwed.01 列。我想看看我是否可以自动化。就像我说的,让我们将所有以wed 开头的列合并在一起。你明白吗?抱歉英语对我不好。
  • 这样比较简单,有一些像'heh'这样的列,我想不考虑吧?
  • @akrun,是的,如果它们是唯一的或者它们独立存在,那么这些列就可以了。只有我的 csv 中的某些列存在此问题,其中很多列是多余的,因为它们只是在 . 之后被赋予了一个新名称
  • 请在下方查看我的解决方案

标签: r dataframe data-cleaning data-wrangling


【解决方案1】:

这是一种选择,我们删除以.('nm1')开头的列名的后缀部分,创建频率table,提取那些具有多个计数的名称('nm2'),循环在这些唯一名称上,使用 grep 从数据集中提取列,并将其分配给创建“组合”列

nm1 <- sub("\\..*", "", names(df))
nm2 <- names(which(table(nm1) > 1))
df[paste0('combined', seq_along(nm2))] <- lapply(nm2, 
        function(x) df[grep(x, names(df))])



df$combined1
#  mon.1 mon.2 mon.2.4.1...1
#1     1     a           #ji
#2     0     b           #ki
#3     1     c          <NA>
#4     4     d           #ui

如果我们希望这是一个list

df[paste0('combined', seq_along(nm2))] <- lapply(nm2, 
        function(x) 
        apply(df[grep(x, names(df))], 1, function(x) as.list(c(x))))


df
#   id mon.1 mon.2 mon.2.4.1...1 tue.6  tue    heh   wed wed.01  thu.0234 rating combined1 combined2    combined3
#1 HD1     1     a           #ji     1  190    1mn  1890   <NA>   @jksdff      1 1, a, #ji   1,  190     1890, NA
#2 HD2     0     b           #ki     2 2345     2a  9002  @ksdf      @sfd      2 0, b, #ki   2, 2345  9002, @ksdf
#3 HD3     1     c          <NA>     3   41    g78 14341   <NA> @kukg.676      3  1, c, NA   3,   41    14341, NA
#4 HD4     4     d           #ui     4   89 asd324   657   <NA>   @jdkfjk      4 4, d, #ui   4,   89      657, NA

【讨论】:

  • @WolfgangBagdanow 如果您检查str(df),则“combined1”、“combined2”、“combined3”等是“data.frame”列。如果你只需要list 就可以了
  • 是的,请,如果可以将它们以列表形式或其他形式保存会很好,因为我会将它们写入文件。我的目标是减少不必要的列创建。我在上面的问题中写下了我的想法
  • @WolfgangBagdanow 在您基于Map 的解决方案中,它将每个元素转换为字符。你想让它保持相同类型还是不同类型,因为mon.1 不是字符
  • @WolfgangBagdanow 我更新了帖子。如果您确定相似的列应该属于同一类型,那似乎合乎逻辑
  • 明白兄弟。是的,它们是相似的类型,我只是提出了一个极端场景案例嘿嘿。非常感谢您的帮助。一如既往地感谢您的帮助!
【解决方案2】:

WolfgangBagdanow-

是的,如果可以将它们以列表形式或 一些东西,因为我会将它们写入文件。我的目标是 减少不必要的列创建。我写下我想要的 我上面的问题

这是对@akrun 的第二个答案的一种扩展。如果您确实决定将此 df 写入 csv 文件,那么请知道 readrdata.tablebase 写入 csv 方法都不会起作用,因为它们还没有实现将列表写入 csv 的方法文件(据我所知)。为了将包含列表列的数据框写入 csv 文件,您需要这样的东西-

#@akrun 's list method-
#df <- data.frame(...)

df[paste0('combined', seq_along(nm2))] <- lapply(nm2, 
        function(x) 
        apply(df[grep(x, names(df))], 1, function(x) as.list(c(x))))

#------------------------------------
set_lists_to_chars <- function(x) {
  if(class(x) == 'list') {
    y <- paste(unlist(x[1]), sep='', collapse=', ')
  } else {
    y <- x 
  }
  return(y)
}
new_frame <- data.frame(lapply(tibble(df), set_lists_to_chars), stringsAsFactors = F)
write.csv(new_frame, file='test.csv')

或者,您也可以使用apply 方法将列表转换为字符。无论如何,这会让你在 csv 中得到想要的东西。希望。顺便说一句,这个问题很好,@akrun 给出了一个很好的答案。祝你好运!

【讨论】:

  • 谢谢@ultapitt 兄弟,我刚刚使用了df &lt;- apply(df,2,as.character),但也感谢您的意见。保重!
【解决方案3】:

好吧,如果您正在尝试为 csv 做准备,一个常见的躲避方法是使用管道将所有困难的部分归功于 @akrun,但是......

nm1 <- sub("\\..*", "", names(df))
nm2 <- names(which(table(nm1) > 1))

df[paste0('combined', seq_along(nm2))] <- lapply(nm2, 
                                                 function(x) 
                                                   apply(df[grep(x, names(df))], 
                                                         1, 
                                                         function(x) str_replace_all(toString(x), 
                                                                                     pattern = ", ", 
                                                                                     replacement = "|")))

> df
   id mon.1 mon.2 mon.2.4.1...1 tue.6  tue    heh   wed wed.01  thu.0234 rating combined1 combined2   combined3
1 HD1     1     a           #ji     1  190    1mn  1890   <NA>   @jksdff      1   1|a|#ji    1| 190     1890|NA
2 HD2     0     b           #ki     2 2345     2a  9002  @ksdf      @sfd      2   0|b|#ki    2|2345  9002|@ksdf
3 HD3     1     c          <NA>     3   41    g78 14341   <NA> @kukg.676      3    1|c|NA    3|  41    14341|NA
4 HD4     4     d           #ui     4   89 asd324   657   <NA>   @jdkfjk      4   4|d|#ui    4|  89      657|NA

【讨论】:

  • 哇,不知道这个。感谢您分享查克 P!保重先生:)
猜你喜欢
  • 2021-06-18
  • 2022-01-17
  • 2014-03-05
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2021-06-01
相关资源
最近更新 更多