在数据框中添加特定行

时间:2019-06-18 01:03:04

标签: r list dataframe structure

我正在尝试将数据帧的特定行添加在一起。

除了没有使用grepl查找线然后将它们重新绑定到底部之外,我不确定是否有更好的方法可以做到这一点。

这是我的输入df:

input = structure(list(
V1 = c("Sales", "Sales", "Sales", "Sales", "Sales","Sales"),
V2 = c("Johnny", "Meg", "Fred", "Johnny", "Meg", "Fred"),
V3 = c("Australia", "Australia", "Australia", "NZ", "NZ","NZ"), 
V4 = c(154L, 1898L, 175L, 1235L, 23L, 255L)), row.names = c(NA,6L),
 class = "data.frame")

这是我的预期输出:

structure(list(
V1 = c("Sales", "Sales", "Sales", "Sales", "Sales", 
"Sales", "Sales", "Sales", "Sales", "Sales", "Sales", "Sales"), 
V2 = c("Johnny", "Meg", "Fred", "Johnny", "Meg", "Fred", "Johnny + Fred", 
"Meg + Fred", "Johnny + Meg + Fred", "Johnny + Fred", "Meg + Fred", 
"Johnny + Meg + Fred"), 
V3 = c("Australia", "Australia", "Australia", "NZ",
 "NZ", "NZ", "Australia", "Australia", "Australia", "NZ", "NZ", "NZ"), 
V4 = c(154L, 1898L, 175L, 1235L, 23L, 255L, 329L, 2073L, 2227L, 1490L, 278L, 1513L)),
 class = "data.frame", row.names = c(NA, -12L)
)

我本以为有一种更好的方法,那就是有一种更好的方法来添加这些行,这些行经过过滤然后再添加,然后加入等。

有人能指出我应寻找的正确方向吗?

2 个答案:

答案 0 :(得分:1)

我使用combn

解决了问题

数据输入部分

input = structure(list(
  V1 = c("Sales", "Sales", "Sales", "Sales", "Sales","Sales"),
  V2 = c("Johnny", "Meg", "Fred", "Johnny", "Meg", "Fred"),
  V3 = c("Australia", "Australia", "Australia", "NZ", "NZ","NZ"), 
  V4 = c(154L, 1898L, 175L, 1235L, 23L, 255L)), row.names = c(NA,6L),
  class = "data.frame")


structure(list(
  V1 = c("Sales", "Sales", "Sales", "Sales", "Sales", 
         "Sales", "Sales", "Sales", "Sales", "Sales", "Sales", "Sales"), 
  V2 = c("Johnny", "Meg", "Fred", "Johnny", "Meg", "Fred", "Johnny + Fred", 
         "Meg + Fred", "Johnny + Meg + Fred", "Johnny + Fred", "Meg + Fred", 
         "Johnny + Meg + Fred"), 
  V3 = c("Australia", "Australia", "Australia", "NZ",
         "NZ", "NZ", "Australia", "Australia", "Australia", "NZ", "NZ", "NZ"), 
  V4 = c(154L, 1898L, 175L, 1235L, 23L, 255L, 329L, 2073L, 2227L, 1490L, 278L, 1513L)),
  class = "data.frame", row.names = c(NA, -12L)
)

解决方案

library(dplyr)

TT = unique(input$V2)
> TT
[1] "Johnny" "Meg"    "Fred"  

comb2 = combn(TT,2,simplify = FALSE)
> comb2

 [[1]]
[1] "Johnny" "Meg"   

[[2]]
[1] "Johnny" "Fred"  

[[3]]
[1] "Meg"  "Fred"

comb3 = combn(TT,3,simplify = FALSE)
> comb3
 [[1]]
[1] "Johnny" "Meg"    "Fred"  

result = function(data){
  purrr::map_df(lapply(data,function(x){paste(x,collapse = '|')}), function(x){
    df = input[grepl(x,input$V2),] %>% group_by(V3)%>%summarize(V1= 'Sales',
                                                                V2= paste(V2,collapse = '+'),
                                                                V4= sum(V4))
    return(df)
  }
  )
}

结果

result(comb2)
# A tibble: 6 x 4
  V3        V1    V2             V4
  <chr>     <chr> <chr>       <int>
1 Australia Sales Johnny+Meg   2052
2 NZ        Sales Johnny+Meg   1258
3 Australia Sales Johnny+Fred   329
4 NZ        Sales Johnny+Fred  1490
5 Australia Sales Meg+Fred     2073
6 NZ        Sales Meg+Fred      278

result(comb3)
# A tibble: 2 x 4
  V3        V1    V2                 V4
  <chr>     <chr> <chr>           <int>
1 Australia Sales Johnny+Meg+Fred  2227
2 NZ        Sales Johnny+Meg+Fred  1513


finalResult = bind_rows(A,B,input) %>%
  select(V1,V2,V3,V4) %>% filter(! V2 %in% c('Johnny+Meg'))

> finalResult 
# A tibble: 12 x 4
   V1    V2              V3           V4
   <chr> <chr>           <chr>     <int>
 1 Sales Johnny+Fred     Australia   329
 2 Sales Johnny+Fred     NZ         1490
 3 Sales Meg+Fred        Australia  2073
 4 Sales Meg+Fred        NZ          278
 5 Sales Johnny+Meg+Fred Australia  2227
 6 Sales Johnny+Meg+Fred NZ         1513
 7 Sales Johnny          Australia   154
 8 Sales Meg             Australia  1898
 9 Sales Fred            Australia   175
10 Sales Johnny          NZ         1235
11 Sales Meg             NZ           23
12 Sales Fred            NZ          255

答案 1 :(得分:0)

使用tidyverse,我们可以首先基于split V3数据框,然后创建名称组合,并添加sum以创建新的小标题并将其绑定到原始数​​据框

library(tidyverse)

input %>%
     bind_rows(input %>%
                   group_split(V3) %>%
                   map_dfr(function(x) map_dfr(2:nrow(x), ~tibble(
                           V1 = first(x$V1), 
                           V2 = combn(x$V2, ., paste, collapse = " + "), 
                           V3 = first(x$V3),
                           V4 = combn(x$V4, .,sum)) %>% 
                           filter(grepl("\\bFred\\b", V2)))))


#      V1                  V2        V3   V4
#1  Sales              Johnny Australia  154
#2  Sales                 Meg Australia 1898
#3  Sales                Fred Australia  175
#4  Sales              Johnny        NZ 1235
#5  Sales                 Meg        NZ   23
#6  Sales                Fred        NZ  255
#7  Sales       Johnny + Fred Australia  329
#8  Sales          Meg + Fred Australia 2073
#9  Sales Johnny + Meg + Fred Australia 2227
#10 Sales       Johnny + Fred        NZ 1490
#11 Sales          Meg + Fred        NZ  278
#12 Sales Johnny + Meg + Fred        NZ 1513

使用相同的逻辑,但在基数R中,我们可以做到

rbind(input, do.call(rbind, lapply(split(input, input$V3), function(x) 
             do.call(rbind, lapply(2:nrow(x), function(y)
        subset(data.frame(V1 = x$V1[1],
                          V2 = combn(x$V2, y, paste, collapse = " + "), 
                          V3 = x$V3[1],
                          V4 = combn(x$V4, y, sum)), 
         grepl("\\bFred\\b", V2)))))))