كيف رقم/تسمية بيانات الجدول من قبل المجموعة عدد من group_by?
سؤال
لدي tbl_df حيث أريد أن group_by(u, v)
لكل متميزة صحيح مزيج لوحظ مع (u, v)
.
تحرير: وحلت هذه المشكلة عن طريق إضافة group_indices()
مرة أخرى في dplyr 0.4.0
أ) ثم تريد تعيين كل مجموعة متميزة بعض التعسفي متميزة عدد التسمية=1,2,3...على سبيل المثالمزيج (u,v)==(2,3) يمكن الحصول على التسمية 1, (1,3) يمكن الحصول على 2 ، وهلم جرا.كيف نفعل هذا مع أحد mutate()
, دون ثلاث خطوات تلخيص و الذاتي الانضمام ؟
dplyr أنيق وظيفة n()
, ولكن هذا يعطي عدد من العناصر داخل المجموعة وليس العام عدد المجموعة. في data.table
وهذا من شأنه أن يسمى ببساطة .GRP
.
ب) في الواقع ما كنت حقا ترغب في تعيين سلسلة/تسمية شخصية ('A','B',...).ولكن ترقيم مجموعات من الاعداد الصحيحه هي جيدة بما فيه الكفاية لأنني ثم يمكن استخدام integer_to_label(i)
كما أدناه.ما لم يكن هناك طريقة ذكية لدمج هذين ؟ ولكن لا تقلق هذا الجزء.
set.seed(1234)
# Helper fn for mapping integer 1..26 to character label
integer_to_label <- function(i) { substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ",i,i) }
df <- tbl_df(data.frame(u=sample.int(3,10,replace=T), v=sample.int(4,10,replace=T)))
# Want to label/number each distinct group of unique (u,v) combinations
df %>% group_by(u,v) %>% mutate(label = n()) # WRONG: n() is number of element within its group, not overall number of group
u v
1 2 3
2 1 3
3 1 2
4 2 3
5 1 2
6 3 3
7 1 3
8 1 2
9 3 1
10 3 4
KLUDGE 1: could do df %>% group_by(u,v) %>% summarize(label = n()) , then self-join
المحلول
تحديث الإجابة
get_group_number = function(){
i = 0
function(){
i <<- i+1
i
}
}
group_number = get_group_number()
df %>% group_by(u,v) %>% mutate(label = group_number())
يمكنك أيضا أن تنظر في ما يلي قليلا غير قابل للقراءة الإصدار
group_number = (function(){i = 0; function() i <<- i+1 })()
df %>% group_by(u,v) %>% mutate(label = group_number())
باستخدام iterators
حزمة
library(iterators)
counter = icount()
df %>% group_by(u,v) %>% mutate(label = nextElem(counter))
نصائح أخرى
dplyr لديه group_indices()
الوظيفة التي يمكنك استخدامها مثل هذا:
df %>%
mutate(label = group_indices(., u, v)) %>%
group_by(label) ...
نهج آخر باستخدام data.table
سيكون
require(data.table)
setDT(df)[,label:=.GRP, by = c("u", "v")]
مما يؤدي إلى:
u v label
1: 2 1 1
2: 1 3 2
3: 2 1 1
4: 3 4 3
5: 3 1 4
6: 1 1 5
7: 3 2 6
8: 2 3 7
9: 3 2 6
10: 3 4 3
تحديث جوابي مع ثلاث طرق مختلفة:
أ) أنيق غير dplyr الحل باستخدام interaction(u,v)
:
> df$label <- factor(interaction(df$u,df$v, drop=T))
[1] 1.3 2.3 2.2 2.4 3.2 2.4 1.2 1.2 2.1 2.1
Levels: 2.1 1.2 2.2 3.2 1.3 2.3 2.4
> match(df$label, levels(df$label)[ rank(unique(df$label)) ] )
[1] 1 2 3 4 5 4 6 6 7 7
ب) جعل راندي أنيق سريعة وقذرة مولد-وظيفة الإجابة أكثر إحكاما:
get_next_integer = function(){
i = 0
function(u,v){ i <<- i+1 }
}
get_integer = get_next_integer()
df %>% group_by(u,v) %>% mutate(label = get_integer())
ج) أيضا هنا هو بطانة واحدة باستخدام وظيفة مولد استغلال عالمي تعيين متغير من هذا:
i <- 0
generate_integer <- function() { return(assign('i', i+1, envir = .GlobalEnv)) }
df %>% group_by(u,v) %>% mutate(label = generate_integer())
rm(i)
ليس لدي ما يكفي من سمعة تعليق, لذلك أنا نشر إجابة بدلا من ذلك.
الحل باستخدام معامل() هو جيد جدا ولكن لا بد أن المجموعة يتم تعيين أرقام بعد (عامل) alphabetizes مستوياته.نفس السلوك يحدث مع dplyr هو group_indices().ربما كنت ترغب في مجموعة الأعداد المسندة من 1 إلى n استنادا إلى المجموعة الحالية من أجل.في هذه الحالة يمكنك استخدام:
my_tibble %>% mutate(group_num = as.integer(factor(group_var, levels = unique(.$group_var))) )