Группировать строки фрейма данных и работать с ними - PullRequest
1 голос
/ 26 марта 2020

У меня есть следующий фрейм данных:

mydata=data.frame(class = c("class 1", "class 2", "class 1", "class 2", "class 3",
                            "class 3", "class 1", "class 2", "class 1", "class 2",
                            "class 3", "class 1", "class 2", "class 3", "class 3"), 
                  word=c("A","B","A","C","A","B","A","C","D", "F", "G", "A", "U",
                         "A", "U"), weight=c(0.1,0.2,0.25,0.01,0.19,0.27,0.32,
                                             0.04,0.005,0.111,0.56,0.056,0.08,
                                             0.099,0.2345))

Для каждого класса, т. Е. class 1, class 2, class 3, я бы хотел удалить из mydata первые три слова (см. столбец word) с большим весом (см. столбец weight). Для моего простого примера, код, который реализует эту задачу:

x=table(mydata$class)
class=names(x)
y=mydata[mydata$class==class[1],]
y=y[order(y$weight,decreasing=TRUE),]
y=head(y,3)

z=mydata[mydata$class==class[2],]
z=z[order(z$weight,decreasing=TRUE),]
z=head(z,3)

w=mydata[mydata$class==class[3],]
w=w[order(w$weight,decreasing=TRUE),]
w=head(w,3)

И затем, желаемый результат:

> y$word
[1] A A A
Levels: A B C D F G U
> z$word
[1] B F U
Levels: A B C D F G U
> w$word
[1] G B U
Levels: A B C D F G U

Если бы у меня было больше классов, я бы использовал для l oop сохранение слов в списке. Но ... Есть ли более простой способ получить этот результат?

Ответы [ 3 ]

2 голосов
/ 26 марта 2020

Использование data.table:

setDT(mydata)
dt = mydata[, lapply(.SD, function(x) x[order(weight, decreasing = T)][1:3]), keyby = class]

> dt
     class word weight
1: class 1    A 0.3200
2: class 1    A 0.2500
3: class 1    A 0.1000
4: class 2    B 0.2000
5: class 2    F 0.1110
6: class 2    U 0.0800
7: class 3    G 0.5600
8: class 3    B 0.2700
9: class 3    U 0.2345
2 голосов
/ 26 марта 2020

Вы можете попробовать использовать dplyr

library(dplyr)

mydata %>% 
  group_by(class) %>% 
  arrange(class, desc(weight)) %>% 
  slice(1:3)

#   class   word  weight
#   <fct>   <fct>  <dbl>
# 1 class 1 A      0.32 
# 2 class 1 A      0.25 
# 3 class 1 A      0.1  
# 4 class 2 B      0.2  
# 5 class 2 F      0.111
# 6 class 2 U      0.08 
# 7 class 3 G      0.56 
# 8 class 3 B      0.27 
# 9 class 3 U      0.234

Редактировать: функция slice выбирает первые 3 строки (в данном случае) для каждой группы в сгруппированном кадре данных. В отличие от top_n, slice отбрасывает возможные связи.

1 голос
/ 26 марта 2020

Вот базовый подход R с выводом, аналогичным вашему запросу.

lapply(split(mydata,mydata$class),function(x){x[order(x$weight,decreasing=TRUE),"word"][1:3]})
$`class 1`
[1] A A A
Levels: A B C D F G U

$`class 2`
[1] B F U
Levels: A B C D F G U

$`class 3`
[1] G B U
Levels: A B C D F G U
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...