मैं दो डेटा फ़्रेमों को एक साथ मिलाने की कोशिश कर रहा हूँ जो patient नामक एक विशिष्ट चर के माध्यम से एक दूसरे से संबंधित हैं। दूसरे डेटा फ़्रेम में एक ही रोगी कॉलम के लिए कई प्रविष्टियाँ हैं। मैं विलय पर डुप्लिकेट रोगी प्रविष्टियां नहीं बनाना चाहता, लेकिन मैं एक कॉलम के तहत मानों को जोड़कर दूसरे डेटा फ्रेम में अद्वितीय जानकारी बनाए रखना चाहता हूं।

मैंने group_by का उपयोग करके कुछ चरों को मैन्युअल रूप से संयोजित करने का प्रयास किया जो काम करता है। हालाँकि, मेरे पास कई चर हैं, और उन सभी को मैन्युअल रूप से निर्दिष्ट करना संभव नहीं है

जैसा कि नीचे देखा गया है, मैं dplyr का उपयोग करके डेटा फ्रेम में प्रत्येक चर को भी जोड़ सकता हूं। दूसरे मामले में समस्या यह है कि डुप्लिकेट मानों को भी जोड़ा जाता है जिससे डेटा फ्रेम अनावश्यक रूप से बड़ा हो जाता है और इससे निपटना मुश्किल हो जाता है। कृपया नीचे रेप्रेक्स देखें।

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

df1 <- data.frame(patient=c("a", "b", "c"), 
                  var1 = 1:3, 
                  var2=11:13)

df1
#>   patient var1 var2
#> 1       a    1   11
#> 2       b    2   12
#> 3       c    3   13



df2 <- data.frame(patient=c("a","a", "b", "b", "c", "c" ), 
                  treatment=  rep(c("drug1", "drug2"), 3), 
                  time= rep(c("time1", "time2"), 3),
                  var3= "constant")

df2
#>   patient treatment  time     var3
#> 1       a     drug1 time1 constant
#> 2       a     drug2 time2 constant
#> 3       b     drug1 time1 constant
#> 4       b     drug2 time2 constant
#> 5       c     drug1 time1 constant
#> 6       c     drug2 time2 constant


df_merged <- left_join(df1, df2)
#> Joining, by = "patient"

# Don't want duplicates like this
df_merged
#>   patient var1 var2 treatment  time     var3
#> 1       a    1   11     drug1 time1 constant
#> 2       a    1   11     drug2 time2 constant
#> 3       b    2   12     drug1 time1 constant
#> 4       b    2   12     drug2 time2 constant
#> 5       c    3   13     drug1 time1 constant
#> 6       c    3   13     drug2 time2 constant



df_merged2 <- df_merged %>%
  group_by(patient) %>%
  mutate(treatment = paste(treatment, collapse = "_"),
         time=paste(time, collapse = "_")) %>%
  filter(!duplicated(patient))

# I can manually edit a few variables like this
df_merged2
#> # A tibble: 3 x 6
#> # Groups:   patient [3]
#>   patient  var1  var2 treatment   time        var3    
#>   <fct>   <int> <int> <chr>       <chr>       <fct>   
#> 1 a           1    11 drug1_drug2 time1_time2 constant
#> 2 b           2    12 drug1_drug2 time1_time2 constant
#> 3 c           3    13 drug1_drug2 time1_time2 constant


df_merged3 <- df_merged %>%
  group_by(patient) %>%
  mutate_at(vars(-group_cols()), .funs = ~paste(., collapse ="_")) %>%
  filter(!duplicated(patient))


# I have many variables I can't specify manually
# I can create this merged data frame, but I don't want to 
# concatenate duplicated values such as var1, var2, and var3
df_merged3
#> # A tibble: 3 x 6
#> # Groups:   patient [3]
#>   patient var1  var2  treatment   time        var3             
#>   <fct>   <chr> <chr> <chr>       <chr>       <chr>            
#> 1 a       1_1   11_11 drug1_drug2 time1_time2 constant_constant
#> 2 b       2_2   12_12 drug1_drug2 time1_time2 constant_constant
#> 3 c       3_3   13_13 drug1_drug2 time1_time2 constant_constant

2019-10-23 को reprex पैकेज द्वारा बनाया गया (v0.3.0)

मैं यह देखना चाहता हूं कि क्या df_merged में पंक्तियों को डुप्लिकेट किए बिना दूसरे डेटा फ्रेम से जानकारी बनाए रखने के लिए केवल अद्वितीय मान वाले चर को संयोजित करने का कोई तरीका है।

मुझे यह जानकर खुशी होगी कि क्या आपके पास dplyr के अलावा अन्य सुझाव हैं। एक data.table समाधान भी मेरे लिए उपयुक्त हो सकता है, क्योंकि मेरे वास्तविक डेटा फ्रेम काफी बड़े हैं।

धन्यवाद!

1
Atakan 24 अक्टूबर 2019, 08:30

1 उत्तर

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

हम summarise_at और unique का उपयोग कर सकते हैं

library(dplyr)
df_merged %>%
          group_by(patient) %>%
          summarise_at(vars(-group_cols()), .funs = ~paste(unique(.), collapse ="_"))

या हम इंटरमीडिएट डेटाफ्रेम के साथ ग्लोबल एनवी को जोड़ने/बदलने के बजाय सीधे मर्ज/संयुक्त कर सकते हैं।

left_join(df1, 
          df2 %>% group_by(patient) %>% 
                  summarise_at(vars(-group_cols()), .funs = ~paste(unique(.), collapse ="_")) %>% 
                  ungroup()
         )

Joining, by = "patient"
  patient var1 var2   treatment        time     var3
1       a    1   11 drug1_drug2 time1_time2 constant
2       b    2   12 drug1_drug2 time1_time2 constant
3       c    3   13 drug1_drug2 time1_time2 constant

अद्यतन

#Here a toy example to experiment with, uncomment browser to see how it works inside Reduce, 
#also see ?Reduce for more info 
paste_mod <- function(x) Reduce(function(u, v){
u <- ifelse(!grepl('_',u) & is.na(u),'.',u)
v <- ifelse(is.na(v),'.',v)
if(v=='.' | !grepl(v,u)) paste0(u,'_',v) else u
}, x)

paste_mod(c("drug1",NA,NA,"drug2","drug1","drug2"))
[1] "drug1_._._drug2"
paste_mod(c(NA,NA,"drug2","drug1","drug2"))
[1] "._._drug2_drug1"

#replace NA with . then apply Reduce
df2 %>% 
       mutate_if(is.factor,as.character) %>% mutate_all(~replace(.,is.na(.),'.')) %>% 
       group_by(patient) %>% 
       summarise_at(vars(-group_cols()), .funs = ~Reduce(function(u, v) if(v=='.' | !grepl(v,u)) paste0(u,'_',v) else u, .)) %>% 
       ungroup()

# A tibble: 2 x 4
  patient treatment       time        var3    
  <chr>   <chr>           <chr>       <chr>   
1 a       drug1_._._drug2 time1_time2 constant
2 c       drug1_drug2     time1_time2 constant

अद्यतन समाधान के परीक्षण के लिए नया df2

df2 <- structure(list(patient = structure(c(1L, 1L, 1L, 1L, 2L, 2L), .Label = c("a", 
"c"), class = "factor"), treatment = structure(c(1L, NA, NA, 
2L, 1L, 2L), .Label = c("drug1", "drug2"), class = "factor"), 
    time = structure(c(1L, 2L, 1L, 2L, 1L, 2L), .Label = c("time1", 
    "time2"), class = "factor"), var3 = structure(c(1L, 1L, 1L, 
    1L, 1L, 1L), class = "factor", .Label = "constant")), class = "data.frame", row.names = c(NA, 
-6L))
1
A. Suliman 25 अक्टूबर 2019, 12:45