मेरे पास एक प्रयोग का डेटाफ्रेम है, जहां प्रतिभागियों को उत्तेजना दिखाई जाती है, और समय को लगातार मापा जाता है।

# reprex
df <- 
    tibble(stim = c(NA, NA, NA, NA, "a", "b", NA, "c", NA, "d", NA, NA, NA),
           time = 0:12)
# A tibble: 13 x 2
   stim   time
   <chr> <int>
 1 NA        0
 2 NA        1
 3 NA        2
 4 NA        3
 5 a         4
 6 b         5
 7 NA        6
 8 c         7
 9 NA        8
10 d         9
11 NA       10
12 NA       11
13 NA       12

मैं एक सामान्यीकृत समाधान बनाना चाहता हूं, tidyverse functions का उपयोग करके क्रमशः पहले और अंतिम मार्कर के बाद डेटा को 1 सेकंड पहले और 2 सेकंड बाद ड्रॉप करने के लिए। Tidyverse का उपयोग करते हुए, मैंने सोचा कि यह काम करेगा, लेकिन यह एक सूचनात्मक त्रुटि फेंकता है।

df %>% 
# store times for first and last stim
    mutate(first_stim = drop_na(stim) %>% pull(time) %>% first(),
           last_stim =  drop_na(stim) %>% pull(time) %>% last()) %>% 
# filter df based on new variables
    filter(time >= first(first_stim) - 1 &
           time <= first(last_stim) + 2)
Error in mutate_impl(.data, dots) : bad value

इसलिए मैंने उत्परिवर्तित करके इस मुद्दे को दूर करने के लिए एक बहुत ही बदसूरत आधार r कोड बनाया:

df2 <- df %>% 
    mutate(first_stim = .[!is.na(.$stim), "time"][1,1],
           last_stim = .[!is.na(.$stim), "time"][nrow(.[!is.na(.$stim), "time"]), 1])
    # A tibble: 13 x 4
       stim   time first_stim last_stim
       <chr> <int> <tibble>   <tibble> 
     1 NA        0 4          9        
     2 NA        1 4          9        
     3 NA        2 4          9        
     4 NA        3 4          9        
     5 a         4 4          9        
     6 b         5 4          9        
     7 NA        6 4          9        
     8 c         7 4          9        
     9 NA        8 4          9        
    10 d         9 4          9        
    11 NA       10 4          9        
    12 NA       11 4          9        
    13 NA       12 4          9   

अब मुझे केवल नए चर first_stim - 1 और last_stim + 2 के आधार पर फ़िल्टर करने की आवश्यकता होगी। लेकिन फ़िल्टर भी विफल रहता है:

df2 %>% 
    filter(time >= first(first_stim) - 1 &
           time <= first(last_stim) + 2)
Error in filter_impl(.data, quo) : 
  Not compatible with STRSXP: [type=NULL].

मैं इसे आधार आर में करने में सक्षम था, लेकिन यह वास्तव में बदसूरत है:

df2[(df2$time >= (df2[[1, "first_stim"]] - 1)) & 
    (df2$time <= (df2[[1, "last_stim"]] + 2))    
    ,]

वांछित आउटपुट इस तरह दिखना चाहिए:

# A tibble: 13 x 2
   stim   time
   <chr> <int>
 4 NA        3
 5 a         4
 6 b         5
 7 NA        6
 8 c         7
 9 NA        8
10 d         9
11 NA       10
12 NA       11

मेरा मानना ​​है कि त्रुटियां dplyr::nth() और संबंधित कार्यों से संबंधित हैं। और मुझे कुछ पुराने मुद्दे मिले हैं जो इस व्यवहार से संबंधित हैं, लेकिन अब मौजूद नहीं होने चाहिए https: //github.com/tidyverse/dplyr/issues/1980 मैं वास्तव में सराहना करता हूं अगर कोई इस बात पर प्रकाश डाल सकता है कि समस्या क्या है, और यह कैसे एक साफ तरीके से करना है।

2
Tamas Nagy 21 मई 2018, 12:53

2 जवाब

सबसे बढ़िया उत्तर

आप is.na और which के संयोजन का उपयोग कर सकते हैं...

library(dplyr)

df <- 
  tibble(stim = c(NA, NA, NA, NA, "a", "b", NA, "c", NA, "d", NA, NA, NA),
         time = 0:12)

df %>% 
  filter(row_number() >= first(which(!is.na(stim))) - 1 & 
         row_number() <= last(which(!is.na(stim))) + 2)

# # A tibble: 9 x 2
#   stim   time
#   <chr> <int>
# 1 NA        3
# 2 a         4
# 3 b         5
# 4 NA        6
# 5 c         7
# 6 NA        8
# 7 d         9
# 8 NA       10
# 9 NA       11

आप अपना पहला प्रयास भी थोड़े संशोधन के साथ कर सकते हैं...

df %>% 
  mutate(first_stim = first(drop_na(., stim) %>% pull(time)),
         last_stim =  last(drop_na(., stim) %>% pull(time))) %>% 
  filter(time >= first(first_stim) - 1 &
           time <= first(last_stim) + 2)
3
CJ Yetman 21 मई 2018, 16:50

हम गैर-एनए मानों का संचयी योग बना सकते हैं और फिर पंक्ति सूचकांक ढूंढ सकते हैं जहां हमें पहले गैर-एनए मान और अंतिम का सामना करना पड़ता है। फिर हम आवश्यकता के आधार पर पंक्तियों का चयन करते हैं। (-1 प्रारंभ से और +2 अंत से)।

library(tidyverse)
df %>%
   mutate(count_cumsum = cumsum(!is.na(stim))) %>%
   slice((which.max(count_cumsum == 1) -1):(which.max(count_cumsum) + 2)) %>%
   select(-count_cumsum)

#  stim   time
#  <chr> <int>
#1 NA        3
#2 a         4
#3 b         5
#4 NA        6
#5 c         7
#6 NA        8
#7 d         9
#8 NA       10
#9 NA       11

केवल यह बताने के लिए कि count_cumsum कैसा दिखता है:

df %>%
   mutate(count_cumsum = cumsum(!is.na(stim)))
 # A tibble: 13 x 3
 # stim   time count_cumsum
 # <chr> <int>        <int>
 #1 NA        0            0
 #2 NA        1            0
 #3 NA        2            0
 #4 NA        3            0
 #5 a         4            1
 #6 b         5            2
 #7 NA        6            2
 #8 c         7            3
 #9 NA        8            3
#10 d         9            4
#11 NA       10            4
#12 NA       11            4
#13 NA       12            4
0
Ronak Shah 21 मई 2018, 13:03