खाली पंक्ति द्वारा डेटाफ्रेम विभाजित करें

Nov 28 2020

मैं NA के ब्लॉक यानी Loc_1, Loc_2, Loc_3 के बीच की पंक्तियों के आधार पर डेटाफ़्रेम की सूची में एक भयानक रूप से स्वरूपित डेटाफ़्रेम को विभाजित करने का प्रयास कर रहा हूं। मैं कोशिश की है खाली पंक्तियों के आधार पर अनुसंधान में विभक्त dataframes और रिक्त पंक्ति और हैडर शीर्षक पर आधारित कई DFS में फूट डालो या विभाजन dataframe कोई भाग्य के साथ। मुझे लगता है कि मेरे मामले में अंतर यह है कि मुझे एनए मान के बिना एक भी कर्नल नहीं मिला है, क्योंकि प्रत्येक नया हिस्सा पहले दो कॉलम में दो पंक्तियों के लिए एनए के साथ शुरू होता है, और एनए के भार पूरे बिखरे हुए हैं। कोई विचार? यह मेरी पहली पोस्ट है, इसलिए यदि मुझे अधिक जानकारी पोस्ट करने की आवश्यकता हो तो कृपया चिल्लाएं!

df <- data.frame(
  a = c(NA, NA, "Loc_1", "Loc_1", "Loc_1", NA, NA, NA, "Loc_2", "Loc_2", "Loc_2", NA, NA, NA, "Loc_3", "Loc_3", "Loc_3"),
  b = c(NA, NA, "25:11:2020", "26:11:2020", "27:11:2020", NA, NA, NA, "25:11:2020", "26:11:2020", "27:11:2020",NA, NA, NA, "25:11:2020", "26:11:2020", "27:11:2020"),
  c = c("Var1", "Unit/1", 1:3, NA, "Var3", "Unit/3", NA, 1, 2, NA,"Var1", "Unit/1", 1:3),
  d = c("Var2", "Unit/2", NA, NA, 1, NA, "Var1", "Unit/1", NA, NA, 1, NA, "Var3", "Unit/3", NA, NA, 1)
)
       a          b      c      d
1   <NA>       <NA>   Var1   Var2
2   <NA>       <NA> Unit/1 Unit/2
3  Loc_1 25:11:2020      1   <NA>
4  Loc_1 26:11:2020      2   <NA>
5  Loc_1 27:11:2020      3      1
6   <NA>       <NA>   <NA>   <NA>
7   <NA>       <NA>   Var3   Var1
8   <NA>       <NA> Unit/3 Unit/1
9  Loc_2 25:11:2020   <NA>   <NA>
10 Loc_2 26:11:2020      1   <NA>
11 Loc_2 27:11:2020      2      1
12  <NA>       <NA>   <NA>   <NA>
13  <NA>       <NA>   Var1   Var3
14  <NA>       <NA> Unit/1 Unit/3
15 Loc_3 25:11:2020      1   <NA>
16 Loc_3 26:11:2020      2   <NA>
17 Loc_3 27:11:2020      3      1

जवाब

6 Edo Nov 28 2020 at 00:46

कैसे इस आधार आर समाधान के बारे में:

n <- rowSums(is.na(df)) == ncol(df)
cs <- cumsum(n) + 1
s <- split(df[!n, ], cs[!n])

s

#> $`1` #> a b c d #> 1 <NA> <NA> Var1 Var2 #> 2 <NA> <NA> Unit/1 Unit/2 #> 3 Loc_1 25:11:2020 1 <NA> #> 4 Loc_1 26:11:2020 2 <NA> #> 5 Loc_1 27:11:2020 3 1 #> #> $`2`
#>        a          b      c      d
#> 7   <NA>       <NA>   Var3   Var1
#> 8   <NA>       <NA> Unit/3 Unit/1
#> 9  Loc_2 25:11:2020   <NA>   <NA>
#> 10 Loc_2 26:11:2020      1   <NA>
#> 11 Loc_2 27:11:2020      2      1
#> 
#> $`3`
#>        a          b      c      d
#> 13  <NA>       <NA>   Var1   Var3
#> 14  <NA>       <NA> Unit/1 Unit/3
#> 15 Loc_3 25:11:2020      1   <NA>
#> 16 Loc_3 26:11:2020      2   <NA>
#> 17 Loc_3 27:11:2020      3      1

आप बड़े करीने से इस तरह से अपने सभी डेटा को फिर से एक लंबे प्रारूप में सेट कर सकते हैं unpivotr:

library(unpivotr)
library(dplyr)
library(purrr)

map_dfr(s, 
        ~ as_cells(.x) %>% 
         behead("up", "var") %>% 
         behead("up", "uom") %>% 
         behead("left", "loc") %>% 
         behead("left", "date") %>% 
         # filter(!is.na(chr)) %>%  # do you need the NAs?
         mutate(value = as.numeric(chr)) %>% 
         select(var, uom, loc, date, value),
        .id = "df")

#> # A tibble: 18 x 6
#>    df    var   uom    loc   date       value
#>    <chr> <chr> <chr>  <chr> <chr>      <dbl>
#>  1 1     Var1  Unit/1 Loc_1 25:11:2020     1
#>  2 1     Var1  Unit/1 Loc_1 26:11:2020     2
#>  3 1     Var1  Unit/1 Loc_1 27:11:2020     3
#>  4 1     Var2  Unit/2 Loc_1 25:11:2020    NA
#>  5 1     Var2  Unit/2 Loc_1 26:11:2020    NA
#>  6 1     Var2  Unit/2 Loc_1 27:11:2020     1
#>  7 2     Var3  Unit/3 Loc_2 25:11:2020    NA
#>  8 2     Var3  Unit/3 Loc_2 26:11:2020     1
#>  9 2     Var3  Unit/3 Loc_2 27:11:2020     2
#> 10 2     Var1  Unit/1 Loc_2 25:11:2020    NA
#> 11 2     Var1  Unit/1 Loc_2 26:11:2020    NA
#> 12 2     Var1  Unit/1 Loc_2 27:11:2020     1
#> 13 3     Var1  Unit/1 Loc_3 25:11:2020     1
#> 14 3     Var1  Unit/1 Loc_3 26:11:2020     2
#> 15 3     Var1  Unit/1 Loc_3 27:11:2020     3
#> 16 3     Var3  Unit/3 Loc_3 25:11:2020    NA
#> 17 3     Var3  Unit/3 Loc_3 26:11:2020    NA
#> 18 3     Var3  Unit/3 Loc_3 27:11:2020     1

यदि आप अंत में एक अद्वितीय डेटाफ़्रेम नहीं चाहते हैं, तो mapइसके बजाय का उपयोग करें map_dfrऔर निकालें, .id = "df"

1 27ϕ9 Nov 28 2020 at 00:44

तुम कोशिश कर सकते हो:

library(dplyr)
library(purrr)

df %>%
  group_split(grp = cumsum(rowSums(is.na(.)) == ncol(.)), .keep = FALSE) %>%
  map_at(.at = -1, tail, -1)

[[1]]
# A tibble: 5 x 4
  a     b          c      d     
  <chr> <chr>      <chr>  <chr> 
1 NA    NA         Var1   Var2  
2 NA    NA         Unit/1 Unit/2
3 Loc_1 25:11:2020 1      NA    
4 Loc_1 26:11:2020 2      NA    
5 Loc_1 27:11:2020 3      1     

[[2]]
# A tibble: 5 x 4
  a     b          c      d     
  <chr> <chr>      <chr>  <chr> 
1 NA    NA         Var3   Var1  
2 NA    NA         Unit/3 Unit/1
3 Loc_2 25:11:2020 NA     NA    
4 Loc_2 26:11:2020 1      NA    
5 Loc_2 27:11:2020 2      1     

[[3]]
# A tibble: 5 x 4
  a     b          c      d     
  <chr> <chr>      <chr>  <chr> 
1 NA    NA         Var1   Var3  
2 NA    NA         Unit/1 Unit/3
3 Loc_3 25:11:2020 1      NA    
4 Loc_3 26:11:2020 2      NA    
5 Loc_3 27:11:2020 3      1    
1 www Nov 28 2020 at 00:55

सुनिश्चित नहीं है कि आपका वांछित आउटपुट। यहाँ मेरा सबसे अच्छा अनुमान है। मैंने प्रत्येक के लिए पहली दो पंक्तियों को हटाने के लिए और अधिक कोड जोड़ा, locक्योंकि वे सिर्फ कॉलम नाम हैं, और फिर मूल पहली पंक्ति के आधार पर नए कॉलम नाम असाइन करें। यह अतिरिक्त चरण आपको Varस्तंभों को संख्यात्मक में बदलने की अनुमति देता है ।

library(tidyverse)

# A helper function to filter rows with any non-NA values
rowAny <- function(x) rowSums(x) > 0

df_list <- df %>%
  # Remove rows with all NA
  filter(rowAny(across(everything(), .fns = function(x) !is.na(x)))) %>%
  # Fill the Loc information
  fill(a, .direction = "up") %>%
  # Split the data frame by a
  split(.$a) %>% # Remove the first two rows and change the column names to the first row (Var1, Var2, Var3, ...) map(function(x){ # Prepare new column names x2 <- x %>% slice(1) %>% t() %>% as.vector() x_names <- c(names(x)[1:2], x2[3:length(x2)]) # Remove the first two rows and assign new column names x3 <- x %>% slice(-1:-2) %>% set_names(x_names) %>% # Change the columns to numeric mutate(across(x2[3:length(x2)], .fns = as.numeric)) return(x3) }) df_list # $Loc_1
#       a          b Var1 Var2
# 1 Loc_1 25:11:2020    1   NA
# 2 Loc_1 26:11:2020    2   NA
# 3 Loc_1 27:11:2020    3    1
# 
# $Loc_2 # a b Var3 Var1 # 1 Loc_2 25:11:2020 NA NA # 2 Loc_2 26:11:2020 1 NA # 3 Loc_2 27:11:2020 2 1 # # $Loc_3
#       a          b Var1 Var3
# 1 Loc_3 25:11:2020    1   NA
# 2 Loc_3 26:11:2020    2   NA
# 3 Loc_3 27:11:2020    3    1