简体   繁体   中英

Adding in blank rows in R dataframe

I have a data frame

data<-data.frame(Type=c("A","B","D","D","E","E"),
                 Ratio=c(5,6,3,3,4,4),
                 Number=c(65,74,43,34,23,12),
                 Letter=c("P","K","M","M","N","B"),
                 Season=c("Fall","Spring","Winter",
                          "Summer","Spring","Winter"))
> data
Type Ratio Number Letter  Season
A     5      65     P       Fall
B     6      74     K       Spring
D     3      43     M       Winter
D     3      34     M       Summer
E     4      23     N       Spring
E     4      12     B       Winter

Where I would like to add new rows to the 'Types' that are only used once(A and B). I would like to add a bow beneath each of there rows that contains the same type,ratio, and number for the one above it, but NA for letter and season. I have used

group_by(Type) 

to start

I would want my final data frame to look like this

Type Ratio Number Letter  Season
A     5      65     P       Fall
A     5      65     NA       NA
B     6      74     K       Spring
B     6      74     NA       NA
D     3      43     M       Winter
D     3      34     M       Summer
E     4      23     N       Spring
E     4      12     B       Winter

Thanks!

Another data.table solution:

setDT(data)[, if (.N == 1L) 
                c(Number = list(Number), .SD[1:2, .(Letter, Season)]) 
              else .SD, 
by=.(Type, Ratio)]
#    Type Ratio Number Letter Season
# 1:    A     5     65      P   Fall
# 2:    A     5     65     NA     NA
# 3:    B     6     74      K Spring
# 4:    B     6     74     NA     NA
# 5:    D     3     43      M Winter
# 6:    D     3     34      M Summer
# 7:    E     4     23      N Spring
# 8:    E     4     12      B Winter

Using data.table :

library(data.table) #1.9.5+
setDT(data)
data<-setkey(rbindlist(list(data,data[,if(.N==1).SD[,!c("Letter","Season"),with=F],by=Type]),fill=T),Type)
> data
   Type Ratio Number Letter Season
1:    A     5     65      P   Fall
2:    A     5     65     NA     NA
3:    B     6     74      K Spring
4:    B     6     74     NA     NA
5:    D     3     43      M Winter
6:    D     3     34      M Summer
7:    E     4     23      N Spring
8:    E     4     12      B Winter

Base package:

d1 <- as.data.frame(table(data$Type))
d2 <- data[data$Type %in% d1[d1$Freq<2,1], 1:3]
d2[, c("Letter", "Season")] <- NA
d3 <- rbind(data, d2)
d3[order(d3$Type), ]

Using dplyr and base package. I've refined my solution based on the use of bind_rows by Nick Kennedy. So I don't need to create my NA columns.

library(dplyr)
d1 <- data %>% group_by(Type) %>% summarize(count = n()) %>% filter (count<2) 
d2 <- data[data$Type %in% d1$Type, 1:3]
d3 <- bind_rows(data, d2)
d3[order(d3$Type), ]

Output:

  Type Ratio Number Letter Season
1    A     5     65      P   Fall
7    A     5     65   <NA>   <NA>
2    B     6     74      K Spring
8    B     6     74   <NA>   <NA>
3    D     3     43      M Winter
4    D     3     34      M Summer
5    E     4     23      N Spring
6    E     4     12      B Winter

Here's a one-line dplyr solution (though printed over multiple lines for clarity):

data %>%
  group_by(Type) %>%
  do(if(nrow(.) > 1) . else bind_rows(., select(., Type, Ratio, Number)))

And if you'd prefer nested pipes to do :

data %>%
  group_by(Type) %>%
  bind_rows(.,
    filter(., n() < 2) %>%
    select(Type, Ratio, Number)
  ) %>%
  arrange(Type)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM