Подсчет количества элементов со значениями x в векторе

351

У меня есть вектор чисел:

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,
         453,435,324,34,456,56,567,65,34,435)

Как я могу подсчитать количество раз, когда в векторе появляется значение x?

Теги:
vector
count
r-faq

14 ответов

422
Лучший ответ

Вы можете просто использовать table():

> a <- table(numbers)
> a
numbers
  4   5  23  34  43  54  56  65  67 324 435 453 456 567 657 
  2   1   2   2   1   1   2   1   2   1   3   1   1   1   1 

Затем вы можете подмножить его:

> a[names(a)==435]
435 
  3

Или преобразуйте его в файл data.frame, если вам удобнее работать с этим:

> as.data.frame(table(numbers))
   numbers Freq
1        4    2
2        5    1
3       23    2
4       34    2
...
  • 16
    Не забывайте о потенциальных проблемах с плавающей точкой, особенно с таблицей, которая приводит числа к строкам.
  • 4
    Это отличный момент. Это все целые числа, так что в данном примере это не проблема, верно?
Показать ещё 8 комментариев
235

Самый прямой способ - sum(numbers == x).

numbers == x создает логический вектор, который является ИСТИННЫМ в каждом месте, где встречается x, и когда sum ing, логический вектор принуждается к числовому, который преобразует TRUE в 1 и FALSE в 0.

Однако обратите внимание, что для чисел с плавающей запятой лучше использовать что-то вроде: sum(abs(numbers - x) < 1e-6).

  • 1
    Хороший вопрос о проблеме с плавающей запятой. Это кусает мою задницу больше, чем я обычно хотел бы признать.
  • 3
    @ Jason, хотя он и дает прямой ответ на вопрос, я предполагаю, что людям понравилось более общее решение, которое дает ответ для всех x в данных, а не конкретное известное значение x . Чтобы быть справедливым, это было то, о чем был первоначальный вопрос. Как я сказал в своем ответе ниже: «Я нахожу, что редко я хочу знать частоту одного значения, а не всех значений ...»
47

Я бы, наверное, сделал что-то вроде этого

length(which(numbers==x))

Но на самом деле лучший способ -

table(numbers)
  • 10
    table(numbers) будет выполнять гораздо больше работы, чем простейшее решение, sum(numbers==x) , потому что она также рассчитывает количество всех других чисел в списке.
  • 1
    проблема с таблицей состоит в том, что ее сложнее включить в более сложное исчисление, например, с помощью apply () на фреймах данных
34

Существует также count(numbers) из plyr пакета. Гораздо удобнее, чем table, на мой взгляд.

32

В моем предпочтительном решении используется rle, который вернет значение (метка, x в вашем примере) и длину, которая представляет, сколько раз это значение появлялось в последовательности.

Объединив rle с sort, вы получите очень быстрый способ подсчитать количество раз, когда появилось какое-либо значение. Это может быть полезно при более сложных проблемах.

Пример:

> numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,324,34,456,56,567,65,34,435)
> a <- rle(sort(numbers))
> a
  Run Length Encoding
    lengths: int [1:15] 2 1 2 2 1 1 2 1 2 1 ...
    values : num [1:15] 4 5 23 34 43 54 56 65 67 324 ...

Если значение, которое вы хотите, не отображается, или вам нужно сохранить это значение позже, сделайте a a data.frame.

> b <- data.frame(number=a$values, n=a$lengths)
> b
    values n
 1       4 2
 2       5 1
 3      23 2
 4      34 2
 5      43 1
 6      54 1
 7      56 2
 8      65 1
 9      67 2
 10    324 1
 11    435 3
 12    453 1
 13    456 1
 14    567 1
 15    657 1

Я нахожу, что редко хочу узнать частоту одного значения, а не все значения, а rle - самый быстрый способ получить счет и сохранить их все.

  • 1
    Преимущество этого, по сравнению с таблицей, в том, что он дает результат в более удобном для использования формате? Спасибо
  • 0
    @HeatherStark Я бы сказал, что есть два преимущества. Во-первых, это, безусловно, более удобный формат, чем вывод таблицы. Во-вторых, иногда я хочу посчитать количество элементов «подряд», а не внутри всего набора данных. Например, c(rep('A', 3), rep('G', 4), 'A', rep('G', 2), rep('C', 10)) вернет values = c('A','G','A','G','C') и lengths=c(3, 4, 1, 2, 10) что иногда полезно.
Показать ещё 2 комментария
16

В R есть стандартная функция для этого

tabulate(numbers)

  • 0
    Недостаток tabulate том, что вы не можете иметь дело с нулевыми и отрицательными числами.
  • 1
    Но вы можете иметь дело с нулем экземпляров данного числа, которые другие решения не обрабатывают
8

Если вы хотите посчитать количество появлений впоследствии, вы можете использовать функцию sapply:

index<-sapply(1:length(numbers),function(x)sum(numbers[1:x]==numbers[x]))
cbind(numbers, index)

Вывод:

        numbers index
 [1,]       4     1
 [2,]      23     1
 [3,]       4     2
 [4,]      23     2
 [5,]       5     1
 [6,]      43     1
 [7,]      54     1
 [8,]      56     1
 [9,]     657     1
[10,]      67     1
[11,]      67     2
[12,]     435     1
[13,]     453     1
[14,]     435     2
[15,]     324     1
[16,]      34     1
[17,]     456     1
[18,]      56     2
[19,]     567     1
[20,]      65     1
[21,]      34     2
[22,]     435     3
  • 0
    Это чем-то быстрее таблицы?
8

здесь один быстрый и грязный способ:

x <- 23
length(subset(numbers, numbers==x))
7
numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435 453,435,324,34,456,56,567,65,34,435)

> length(grep(435, numbers))
[1] 3


> length(which(435 == numbers))
[1] 3


> require(plyr)
> df = count(numbers)
> df[df$x == 435, ] 
     x freq
11 435    3


> sum(435 == numbers)
[1] 3


> sum(grepl(435, numbers))
[1] 3


> sum(435 == numbers)
[1] 3


> tabulate(numbers)[435]
[1] 3


> table(numbers)['435']
435 
  3 


> length(subset(numbers, numbers=='435')) 
[1] 3
7

Вы можете изменить номер на все, что пожелаете, в следующей строке

length(which(numbers == 4))
3

Использование таблицы, но без сравнения с names:

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435)
x <- 67
numbertable <- table(numbers)
numbertable[as.character(x)]
#67 
# 2 

table полезен, если вы несколько раз используете подсчеты разных элементов. Если вам нужен только один счетчик, используйте sum(numbers == x)

2

Еще один способ, которым я нахожу удобным, - это

numbers <- c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,324,34,456,56,567,65,34,435)
(s<-summary (as.factor(numbers)))

Это преобразует набор данных в коэффициент, а затем summary() дает нам контрольные итоги (количество уникальных значений).

Выход:

4   5  23  34  43  54  56  65  67 324 435 453 456 567 657 
2   1   2   2   1   1   2   1   2   1   3   1   1   1   1 

Это может быть сохранено как файл данных, если это необходимо.

as.data.frame(cbind (Number = names (s), Freq = s), strAsAsFactors = F, row.names = 1: length (s))

Здесь row.names используется для переименования имен строк. без использования row.names, имена столбцов в s используются как имена строк в новой области данных

Выход:

     Number Freq
1       4    2
2       5    1
3      23    2
4      34    2
5      43    1
6      54    1
7      56    2
8      65    1
9      67    2
10    324    1
11    435    3
12    453    1
13    456    1
14    567    1
15    657    1
1

Существуют разные способы подсчета конкретных элементов

library(plyr)
numbers =c(4,23,4,23,5,43,54,56,657,67,67,435,453,435,7,65,34,435)

print(length(which(numbers==435)))

#Sum counts number of TRUE in a vector 
print(sum(numbers==435))
print(sum(c(TRUE, FALSE, TRUE)))

#count is present in plyr library 
#o/p of count is a DataFrame, freq is 1 of the columns of data frame
print(count(numbers[numbers==435]))
print(count(numbers[numbers==435])[['freq']])
0

Это может быть сделано с outer получить Metrix равенств с последующими rowSums, с очевидным значением.
Чтобы иметь счетчики и numbers в одном наборе данных, сначала создается data.frame. Этот шаг не нужен, если вы хотите раздельный ввод и вывод.

df <- data.frame(No = numbers)
df$count <- rowSums(outer(df$No, df$No, FUN = '=='))

Ещё вопросы

Сообщество Overcoder
Наверх
Меню