【问题标题】:Modying R data frame based on two columns基于两列修改R数据框
【发布时间】:2019-09-11 05:14:56
【问题描述】:

我正在尝试修改以下 R 数据框:

Column1         Column2            Value1            Value2
Parent1         Child1             3                 12
Parent1         Child2             4                 12
Parent1         Child3             5                 12
Parent2         Child4             2                 9
Parent2         Child5             6                 9
Parent2         Child6             1                 9

我想将“父”条目放在“子”条目上方,并将值从“Value2”移动到“Value1”。新的数据框是这样的:

Column2         Value1            
Parent1         12
   Child1       3                
   Child2       4                
   Child3       5                 
Parent2         9
   Child4       2                 
   Child5       6                 
   Child6       1          

这可以使用 dplyr 完成吗?另外,有没有办法在“儿童”条目中添加任何额外的空白?

感谢您的任何见解。

【问题讨论】:

  • 只是好奇,以这种方式构建数据的目的是什么?
  • 这是一个我正在处理分层数据的项目。
  • 这样做,你会失去你的结构。在这样的框架中,您可能不会保留 child1-parent1 关系。我建议您以保留的格式保存数据。
  • 感谢您的评论。不过,我还是想看看这是怎么做到的。
  • xmljson 更适合这种情况。

标签: r dataframe dplyr


【解决方案1】:

准备数据

library(tidyverse)
data <- read_delim(
    "Column1         Column2            Value1            Value2
Parent1         Child1             3                 12
Parent1         Child2             4                 12
Parent1         Child3             5                 12
Parent2         Child4             2                 9
Parent2         Child5             6                 9
Parent2         Child6             1                 9",delim = " "
) %>%
    mutate_all(~str_remove_all(.x," "))
colnames(data) <- str_remove_all(colnames(data)," ")

使用tidyr::nest()“清理”数据,以便我们可以逐行迭代数据帧。

nested_data <- data %>%
    group_by(Column1,Value2) %>%
    nest()
> nested_data
# A tibble: 2 x 3
  Column1 Value2 data            
  <chr>   <chr>  <list>          
1 Parent1 12     <tibble [3 x 2]>
2 Parent2 9      <tibble [3 x 2]>

然后使用pmap_df()构造所需的输出。

pmap_df(nested_data,function(...){
    values = list(...)
    bind_rows(
        tibble(
            Column2 = values$Column1,
            Value1 = values$Value2
        )
        ,
        values$data %>%
            mutate(Column2 = paste0("  ",Column2)) # add white space
    )
})

# A tibble: 8 x 2
  Column2    Value1
  <chr>      <chr> 
1 Parent1    12    
2 "  Child1" 3     
3 "  Child2" 4     
4 "  Child3" 5     
5 Parent2    9     
6 "  Child4" 2     
7 "  Child5" 6     
8 "  Child6" 1 

【讨论】:

  • 您是如何让Column2 左对齐的?对我来说,它保持右对齐。
  • 我在你的回答中看到,输出是内置的 R data.frame,而我的输出是 tibble。我认为它们在 R 控制台中的显示方式不同,如果导出为其他格式,这应该不是问题。
  • 啊!说得通。谢谢!
【解决方案2】:

这是dplyr 中的另一种方式。可以删除group 列,如果需要,可以使arrange 逻辑更加健壮。 -

df %>% 
  mutate(group = group_indices(., Column1)) %>%
  {bind_rows(
    distinct(., Column = Column1, Value = Value2, group),
    select(., Column = Column2, Value = Value1, group) %>% 
      mutate(Column = paste0("   ", Column))
  )} %>% 
  arrange(group, desc(Column))

# A tibble: 8 x 3
  Column      Value group
  <chr>       <int> <int>
1 Parent1        12     1
2 "   Child3"     5     1
3 "   Child2"     4     1
4 "   Child1"     3     1
5 Parent2         9     2
6 "   Child6"     1     2
7 "   Child5"     6     2
8 "   Child4"     2     2

数据 -

df <- structure(list(Column1 = c("Parent1", "Parent1", "Parent1", "Parent2", 
"Parent2", "Parent2"), Column2 = c("Child1", "Child2", "Child3", 
"Child4", "Child5", "Child6"), Value1 = c(3L, 4L, 5L, 2L, 6L, 
1L), Value2 = c(12L, 12L, 12L, 9L, 9L, 9L)), .Names = c("Column1", 
"Column2", "Value1", "Value2"), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

【讨论】:

    【解决方案3】:

    这是data.table 解决方案:

    library(data.table)
    
    DT[, GRP := .GRP, by = Column1]
    DT[, ID := .I]
    
    DT_bind <- rbindlist(list(DT[, .(Value1 = first(Value2), .GRP, ID = NA_integer_), by = .(Column2 = Column1)]
                   ,DT[, .(Column2, Value1, GRP, ID)]))
    
    setorder(DT_bind, GRP, ID)
    
    DT_bind[, .(Column2, Value1)]
    
       Column2 Value1
    1: Parent1     12
    2:  Child1      3
    3:  Child2      4
    4:  Child3      5
    5: Parent2      9
    6:  Child4      2
    7:  Child5      6
    8:  Child6      1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多