Data.table: Keyby/рд╕рдмрд╕реЗрдЯрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдЕрджреНрд╡рд┐рддреАрдп рд╕рдореВрд╣реЛрдВ рдХреЛ рд╡рд╛рдкрд╕ рдирд╣реАрдВ рдХрд░рдХреЗ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 31 рдорд╛рд░реНрдЪ 2018  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: Rdatatable/data.table

рдиреАрдЪреЗ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдЬрд╣рд╛рдВ keyby (рджреНрд╡рд╛рд░рд╛ рднреА) рдЕрджреНрд╡рд┐рддреАрдп рд╕рдореВрд╣реЛрдВ рдХреЛ рд╕рдмрд╕реЗрдЯрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рд╡рд╛рдкрд╕ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдПрдХ рдмрд╛рд░ рд╕рдмреНрдорд┐рдЯрд┐рдВрдЧ рд╣рдЯрд╛ рджрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж, keyby рдареАрдХ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

library(data.table)
# data.table 1.10.5 IN DEVELOPMENT built 2018-03-21 23:49:00 UTC; travis
#  The fastest way to learn (by data.table authors): https://www.datacamp.com/courses/data-analysis-the-data-table-way
#  Documentation: ?data.table, example(data.table) and browseVignettes("data.table")
#  Release notes, videos and slides: http://r-datatable.com

# small dataset
dat <- data.table(Group = rep(c("All", "Not All"), times = 4), count = 1:8, ID = rep(1:2, each = 4))

# keyby returning non unique IDs with subset
dat[Group == "All" ,lapply(.SD, function(x) sum(x, na.rm = TRUE)), .SDcols= c("count"), keyby = ID, verbose = TRUE]
# Creating new index 'Group'
# Creating index Group done in ... 0.001sec 
# Optimized subsetting with index 'Group'
# on= matches existing index, using index
# Starting bmerge ...done in 0.000sec 
# i clause present and columns used in by detected, only these subset: ID 
# Finding groups using forderv ... 0.000sec 
# Finding group sizes from the positions (can be avoided to save RAM) ... 0.000sec 
# lapply optimization changed j from 'lapply(.SD, function(x) sum(x, na.rm = TRUE))' to 'list(..FUN1(count))'
# GForce is on, left j unchanged
# Old mean optimization is on, left j unchanged.
# Making each group and running j (GForce FALSE) ... 
#   collecting discontiguous groups took 0.000s for 2 groups
#   eval(j) took 0.000s for 2 calls
# 0.000sec 
#    ID count
# 1:  1     4
# 2:  1    12

# keyby working fine without subset
dat[,lapply(.SD, function(x) sum(x, na.rm = TRUE)), .SDcols= c("count"), keyby = ID] 
# Finding groups using forderv ... 0.000sec 
# Finding group sizes from the positions (can be avoided to save RAM) ... 0.000sec 
# lapply optimization changed j from 'lapply(.SD, function(x) sum(x, na.rm = TRUE))' to 'list(..FUN1(count))'
# GForce is on, left j unchanged
# Old mean optimization is on, left j unchanged.
# Making each group and running j (GForce FALSE) ... 
#   memcpy contiguous groups took 0.000s for 2 groups
#   eval(j) took 0.000s for 2 calls
# 0.000sec 
#    ID count
# 1:  1    10
# 2:  2    26

sessionInfo()
R version 3.4.4 (2018-03-15)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Debian GNU/Linux 9 (stretch)
Matrix products: default
BLAS: /usr/lib/openblas-base/libblas.so.3
LAPACK: /usr/lib/libopenblasp-r0.2.19.so
locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=C             
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     
other attached packages:
[1] data.table_1.10.5
loaded via a namespace (and not attached):
[1] compiler_3.4.4

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рд╕рд╣рдордд рд╣реВрдБ рдХрд┐ рдпрд╣ рдПрдХ рдмрдЧ рд╣реИред

рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрдиреБрд╢рдВрд╕рд┐рдд рдХреЛрдб рд╣реИ:

dat[Group == "All", lapply(.SD, sum, na.rm = TRUE), .SDcols= c("count"), keyby = ID]

рдЬреЛ рд╕рд╣реА рдЙрддреНрддрд░ рджреЗрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рдВрд╕реНрдХрд░рдг GForce рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░реЗрдЧрд╛ рдФрд░ рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдмрдЧ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред

рдмреЗрд╢рдХ рдпрд╣ рдХреЛрдИ рдорджрдж рдирд╣реАрдВ рд╣реИ рдЕрдЧрд░ рдЖрдкрдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреЛрдб рдЗрд╕ рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЕрдЧрд░ рд╣рдо рд╕рдмрд╕реЗрдЯ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рд╕реАрдзреЗ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреЛрдб рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

dat[c(1, 3, 5, 7),
    lapply(.SD, function(x) sum(x, na.rm = TRUE)),
    .SDcols= "count", keyby = ID, verbose = TRUE]
# i clause present and columns used in by detected, only these subset: ID 
# Finding groups using forderv ... 0.000sec 
# Finding group sizes from the positions (can be avoided to save RAM) ... 0.000sec 
# lapply optimization changed j from 'lapply(.SD, function(x) sum(x, na.rm = TRUE))' to 'list(..FUN1(count))'
# GForce is on, left j unchanged
# Old mean optimization is on, left j unchanged.
# Making each group and running j (GForce FALSE) ... 
#   collecting discontiguous groups took 0.000s for 2 groups
#   eval(j) took 0.000s for 2 calls
# 0.000sec 
#    ID count
# 1:  1     4
# 2:  2    12

рдореБрдЭреЗ verbose рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рдирд┐рдореНрди рдЕрдВрддрд░ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ:

рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ 'рд╕рдореВрд╣' рдХреЗ рд╕рд╛рде рдЕрдиреБрдХреВрд▓рд┐рдд рдЙрдкрд╕рдореБрдЪреНрдЪрдп

рдЗрд╕рдиреЗ рдореБрдЭреЗ рд╕реАрдЖрд░рдПрдПрди рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд┐рдпрд╛; рдХреЛрдб 1.10.4-3 рдкрд░ рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд┐рдирд╛ рдЪрд▓рддрд╛ рд╣реИред

рддреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдмрд╕реЗрдЯ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдкрд░ @MarkusBonsch рдХреЗ рдХрд╛рдо рд╕реЗ рдХреБрдЫ рд╣реИ?

рдЕрдЧрд░ рд╣рдо рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдореБрдЭреЗ рднреА рд╡рд╣реА рддреНрд░реБрдЯрд┐ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ:

dat[.('All'), on = 'Group',
    lapply(.SD, function(x) sum(x, na.rm = TRUE)),
    .SDcols= "count", keyby = ID]
#    ID count
# 1:  1     4
# 2:  1    12

рд▓реЗрдХрд┐рди рдХреБрдВрдЬреА рд╕рдВрд╕реНрдХрд░рдг рдареАрдХ рд╣реИ:

setkey(dat, Group)
dat[.('All'), 
    lapply(.SD, function(x) sum(x, na.rm = TRUE)),
    .SDcols= "count", keyby = ID]#    ID count
# 1:  1     4
# 2:  2    12

рд╕рднреА 4 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рд╕рд╣рдордд рд╣реВрдБ рдХрд┐ рдпрд╣ рдПрдХ рдмрдЧ рд╣реИред

рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрдиреБрд╢рдВрд╕рд┐рдд рдХреЛрдб рд╣реИ:

dat[Group == "All", lapply(.SD, sum, na.rm = TRUE), .SDcols= c("count"), keyby = ID]

рдЬреЛ рд╕рд╣реА рдЙрддреНрддрд░ рджреЗрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рдВрд╕реНрдХрд░рдг GForce рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░реЗрдЧрд╛ рдФрд░ рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдмрдЧ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред

рдмреЗрд╢рдХ рдпрд╣ рдХреЛрдИ рдорджрдж рдирд╣реАрдВ рд╣реИ рдЕрдЧрд░ рдЖрдкрдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреЛрдб рдЗрд╕ рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЕрдЧрд░ рд╣рдо рд╕рдмрд╕реЗрдЯ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рд╕реАрдзреЗ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреЛрдб рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

dat[c(1, 3, 5, 7),
    lapply(.SD, function(x) sum(x, na.rm = TRUE)),
    .SDcols= "count", keyby = ID, verbose = TRUE]
# i clause present and columns used in by detected, only these subset: ID 
# Finding groups using forderv ... 0.000sec 
# Finding group sizes from the positions (can be avoided to save RAM) ... 0.000sec 
# lapply optimization changed j from 'lapply(.SD, function(x) sum(x, na.rm = TRUE))' to 'list(..FUN1(count))'
# GForce is on, left j unchanged
# Old mean optimization is on, left j unchanged.
# Making each group and running j (GForce FALSE) ... 
#   collecting discontiguous groups took 0.000s for 2 groups
#   eval(j) took 0.000s for 2 calls
# 0.000sec 
#    ID count
# 1:  1     4
# 2:  2    12

рдореБрдЭреЗ verbose рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рдирд┐рдореНрди рдЕрдВрддрд░ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ:

рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ 'рд╕рдореВрд╣' рдХреЗ рд╕рд╛рде рдЕрдиреБрдХреВрд▓рд┐рдд рдЙрдкрд╕рдореБрдЪреНрдЪрдп

рдЗрд╕рдиреЗ рдореБрдЭреЗ рд╕реАрдЖрд░рдПрдПрди рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд┐рдпрд╛; рдХреЛрдб 1.10.4-3 рдкрд░ рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд┐рдирд╛ рдЪрд▓рддрд╛ рд╣реИред

рддреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдмрд╕реЗрдЯ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдкрд░ @MarkusBonsch рдХреЗ рдХрд╛рдо рд╕реЗ рдХреБрдЫ рд╣реИ?

рдЕрдЧрд░ рд╣рдо рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдореБрдЭреЗ рднреА рд╡рд╣реА рддреНрд░реБрдЯрд┐ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ:

dat[.('All'), on = 'Group',
    lapply(.SD, function(x) sum(x, na.rm = TRUE)),
    .SDcols= "count", keyby = ID]
#    ID count
# 1:  1     4
# 2:  1    12

рд▓реЗрдХрд┐рди рдХреБрдВрдЬреА рд╕рдВрд╕реНрдХрд░рдг рдареАрдХ рд╣реИ:

setkey(dat, Group)
dat[.('All'), 
    lapply(.SD, function(x) sum(x, na.rm = TRUE)),
    .SDcols= "count", keyby = ID]#    ID count
# 1:  1     4
# 2:  2    12

рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП @cathine рдФрд░ рдЬрд╛рдВрдЪ рдХреЗ рд▓рд┐рдП @MichaelChirico рдХреЛ рдзрдиреНрдпрд╡рд╛рджред
рдореВрд▓ рдХрд╛рд░рдг рдорд╛рдЗрдХрд▓ рджреНрд╡рд╛рд░рд╛ рдмрддрд╛рдП рдЧрдП рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдХрд╛ рдЫреЛрдЯрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИ:
dat[.('All'), on = 'Group', lapply(.SD, function(x) sum(x, na.rm = TRUE)), .SDcols= "count", keyby = ID]

рдЬрдм рдпрд╣ рд╕рдорд╕реНрдпрд╛ #2591 рд╣рд▓ рд╣реЛ рдЬрд╛рдПрдЧреА, рддреЛ рд╢рд╛рдпрдж рд╕реБрд▓рдЭ рдЬрд╛рдПрдЧреАред
рдирдП рдЙрдкрд╕рдореБрдЪреНрдЪрдп рдЕрдиреБрдХреВрд▓рди рдореЗрдВ, рдЙрдкрд╕рдореБрдЪреНрдЪрдп рдХреЛ data.table рд╕рдореНрдорд┐рд▓рд┐рдд рднрд╛рдЧ рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдмрдЧ рдЕрдм рдЙрдкрд╕рдореБрдЪреНрдЪрдп рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдЬреБрдбрд╝рдиреЗ рдХреЛ рднреА рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЕрдЧрд░ рдореИрдВ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рддреЛ рдореИрдВ ASAP рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред
рддрдм рддрдХ, рдЖрдк рдЗрд╕рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП dat[Group == "All"][ ,lapply(.SD, function(x) sum(x, na.rm = TRUE)), .SDcols= c("count"), keyby = ID, verbose = TRUE] ред
рдЕрд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдЦреЗрдж рд╣реИред

рдзрдиреНрдпрд╡рд╛рдж @ рдХреИрдерд┐рди! рдкреБрд╖реНрдЯрд┐ рдХреА рдЧрдИ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓-рджреЗрд╡ рд╣реИ рдФрд░ рдЗрд╕реЗ options(datatable.optimize=2) рд╕рд╛рде рдХрдо рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рдорд╕реНрдпрд╛ рд╕реНрддрд░ 3 рдЕрдиреБрдХреВрд▓рди рдореЗрдВ рдкреНрд░рддреАрдд рд╣реЛрддреА рд╣реИред рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдБ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдлрд┐рд╕рд▓рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛!
рдПрдХ рдЕрдиреНрдп рд╕рдВрдкрд░реНрдХ рд╕реЗ рдФрд░ рднреА рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рд░рд┐рдкреЛрд░реНрдЯ рднреА рдХреА:

> DT = data.table(
    id = c("a","a","a","b","b","c","c","d","d"),
    group = c(1,1,1,1,1,2,2,2,2),
    num = 1)
> DT[, uniqueN(id), by=group]          # ok 
   group    V1
   <num> <int>
1:     1     2
2:     2     2
> DT[num==1, uniqueN(id), by=group]    # group column wrong
   group    V1
   <num> <int>
1:     1     2
2:     1     2
> options(datatable.optimize=2)
> DT[num==1, uniqueN(id), by=group]    # ok
   group    V1
   <num> <int>
1:     1     2
2:     2     2
> options(datatable.optimize=3)        # not ok
> DT[num==1, uniqueN(id), by=group]
   group    V1
   <num> <int>
1:     1     2
2:     1     2
> DT[num==1, sum(num), by=group]       # ok
   group    V1
   <num> <num>
1:     1     7
2:     2     4
> DT[num==1, length(num), by=group]    # not ok
   group    V1
   <num> <int>
1:     1     7
2:     1     4
> options(datatable.optimize=2)        # ok
> DT[num==1, length(num), by=group]
   group    V1
   <num> <int>
1:     1     7
2:     2     4
> 

рдпрд╣ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреНрдпреЛрдВ рдлрд┐рд╕рд▓ рдЧрдпрд╛? рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рддрднреА рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдЧреНрд░реБрдкрд┐рдВрдЧ рдХреЙрд▓рдо рдХреЛ рд╕реЙрд░реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдиреАрдЪреЗ рдХреЛрдб рджреЗрдЦреЗрдВ)! рдореИрдВрдиреЗ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реЙрд░реНрдЯ рдХрд┐рдП рдЧрдП рдХреЙрд▓рдо рдкрд░ рдЧреНрд░реБрдкрд┐рдВрдЧ рдХреА рдЬрд╛рдВрдЪ рдирд╣реАрдВ рдХреАред

library(data.table)
DT = data.table(
  id = c("a","a","a","b","b","c","c","d","d"),
  group = c(1,1,1,1,1,2,2,2,2),
  group2 = c(1,1,1,1,1,2,2,2,1),
  num = 1)
DT[, uniqueN(id), by=group]          # ok 
# group    V1
# <num> <int>
# 1:     1     2
# 2:     2     2
DT[num==1, uniqueN(id), by=group]    # group column wrong
# group    V1
# <num> <int>
# 1:     1     2
# 2:     1     2
DT[num==1, uniqueN(id), by=group2]    # ok with other group column that is not sorted
# group2 V1
# 1:      1  3
# 2:      2  2

setkey(DT, group2)
DT[num==1, uniqueN(id), by=group2]    # not ok anymore since the group column is sorted now
# group2 V1
# 1:      1  3
# 2:      1  2
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

arunsrinivasan picture arunsrinivasan  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

st-pasha picture st-pasha  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

symbalex picture symbalex  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

DavidArenburg picture DavidArenburg  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

mattdowle picture mattdowle  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ