Фильтруйте строки, содержащие 2 или более экземпляров определенных значений в R

#r

Вопрос:

У меня возникли проблемы с составлением таблицы частот, в которой данные представлены в нескольких столбцах.Мой набор данных структурирован следующим образом:

 ID shape shape2 shape3 shape4 shape5  12 triangle rhombus circle square rectangle 68 hexagon NA NA NA NA 32 rectangle octagon square NA NA 18 square triangle NA NA NA  27. circle. NA. NA. NA. NA 77. square. trapezoid. triangle. NA. NA   

Я хочу получить таблицу частот всех различных форм, например, такую:

 shape. freq triangle. 3 square. 4 circle. 2 hexagon. 1 octagon. 1 trapezoid. 1 rhombus. 1 rectangle 2  

Тогда меня действительно интересуют только 5 фигур, поэтому я хотел бы, чтобы это выглядело так:

 shape. freq triangle. 3 square. 4 circle. 2 rectangle 2  

Спасибо!

Ответ №1:

Допустим, у вас есть ваши данные в dat, затем:

 library(data.table) data.table(table(gsub("\.", "", unlist(dat[,-1]))))[Ngt;=2]  

Обратите внимание, что я удалил . из некоторых имен. data.table на самом деле в этом нет необходимости, я просто нахожу синтаксис [Ngt;=2] более чистым и удобным, чем альтернативы base-r.

Для альтернативы base-r:

 subset(data.frame(table(gsub("\.", "", unlist(dat[,-1])))), Freq gt; 2)  
 V1 N 1: circle 2 2: NA 4 3: rectangle 2 4: square 4 5: triangle 3  

Комментарии:

1. Этого строго не требуется data.table , это тоже будет работать в базе: subset(data.frame(table(gsub("[.]$","",unlist(dat[,-1])))), Freq gt; 1)

2. @r2evans Это правда, мне лично просто не очень нравится синтаксис base-r для вложенных фреймов data.frames.

3. Это не проблема, и я не пытался убедить вас изменить свой ответ. Возможно, увеличить его, а не изменить. Я предоставил комментарий основном в качестве эталона для пользователей, которые могут быть склонны к добавлению нового пакета только для одного этапа в своих данных трубопроводам; в этом случае, если они уже не помощью data.table , а не толчок, чтобы научиться этому, то, возможно, выше код-гольф subset(., Freq gt; 1) будет достаточно хорош, чтобы использовать ядро методологии.

4. @r2evans да, я знаю — спасибо за комментарий 🙂

Ответ №2:

Работает ли это:

 library(dplyr) library(tidyr)  df %gt;% pivot_longer(-ID, values_to = 'shape') %gt;% count(shape, name = 'freq') %gt;% filter(shape %in% c('triangle','square','circle','rectangle'))  # A tibble: 4 x 2  shape freq  lt;chrgt; lt;intgt; 1 circle 2 2 rectangle 2 3 square 4 4 triangle 3  

Ответ №3:

Другое решение, основанное также на data.table :

 library(data.table)  dt lt;- data.table::data.table(  ID = c(12L, 68L, 32L, 18L, 27L, 77L),  shape = c("triangle","hexagon",  "rectangle","square","circle","square"),  shape2 = c("rhombus", NA, "octagon", "triangle", NA, "trapezoid"),  shape3 = c("circle", NA, "square", NA, NA, "triangle"),  shape4 = c("square", NA, NA, NA, NA, NA),  shape5 = c("rectangle", NA, NA, NA, NA, NA) )  melt(dt, id="ID", 2:6, na.rm = T, value.name = "shape"  )[,.(freq = .N), by = "shape"][freq gt; 1]  #gt; shape freq #gt; 1: triangle 3 #gt; 2: rectangle 2 #gt; 3: square 4 #gt; 4: circle 2