Подсчет строк в кадре данных в соответствии с несколькими условиями [дубликат]

function isObject(obj) {
    return obj !== null && typeof obj === 'object';
}
const isArray = Array.isArray;

function isPlainObject(obj) {
    return isObject(obj) && (
        obj.constructor === Object  // obj = {}
        || obj.constructor === undefined // obj = Object.create(null)
    );
}

function mergeDeep(target, ...sources){
    if (!sources.length) return target;
    const source = sources.shift();

    if (isPlainObject(source) || isArray(source)) {
        for (const key in source) {
            if (isPlainObject(source[key]) || isArray(source[key])) {
                if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
                    target[key] = {};
                }else if (isArray(source[key]) && !isArray(target[key])) {
                    target[key] = [];
                }
                mergeDeep(target[key], source[key]);
            } else if (source[key] !== undefined && source[key] !== '') {
                target[key] = source[key];
            }
        }
    }

    return mergeDeep(target, ...sources);
}

// test...
var source = {b:333};
var source2 = {c:32, arr: [33,11]}
var n = mergeDeep({a:33}, source, source2);
source2.arr[1] = 22;
console.log(n.arr); // out: [33, 11]
313
задан epo3 4 October 2016 в 11:29
поделиться

12 ответов

Вы можете просто использовать 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
...
396
ответ дан Shane 16 August 2018 в 04:06
поделиться
  • 1
    Не забывайте о потенциальных проблемах с плавающей запятой, особенно с таблицей, которая забирает числа в строки. – hadley 17 December 2009 в 19:10
  • 2
    Это отличный момент. Это все целые числа, поэтому в этом примере это не проблема. Не так ли? – Shane 17 December 2009 в 19:18
  • 3
    не совсем. Элементы таблицы имеют класс целочисленного класса (таблица (числа) [1]), но 435 - число с плавающей запятой. Чтобы сделать его целым числом, вы можете использовать 435L. – Ian Fellows 18 December 2009 в 03:11
  • 4
    @Ian - Я смущен, почему 435 - это float в этом примере. Вы можете немного уточнить? Благодарю. – Heather Stark 31 January 2013 в 15:52
  • 5
    Почему не a["435"] вместо a[names(a)==435]? – pomber 26 December 2014 в 18:08

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

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
2
ответ дан Akash 16 August 2018 в 04:06
поделиться

Если вы хотите посчитать количество появлений впоследствии, вы можете использовать функцию 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
7
ответ дан Berny 16 August 2018 в 04:06
поделиться
  • 1
    Это каким-то образом быстрее, чем таблица? – Garini 30 May 2018 в 13:24

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

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

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

217
ответ дан hadley 16 August 2018 в 04:06
поделиться
  • 1
    Хороший вопрос о проблеме с плавающей запятой. Это кусает мою задницу больше, чем я обычно признаю. – JD Long 17 December 2009 в 19:13
  • 2
    @Jason, пока он напрямую отвечает на вопрос, я думаю, что людям понравилось более общее решение, которое дает ответ для всех x в данных, а не определенное известное значение x. Справедливости ради, в этом и был исходный вопрос. Как я уже сказал в своем ответе ниже, «я нахожу, что мне редко приходится знать частоту одного значения, а не все значения ...» – JBecker 22 April 2013 в 21:46
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
5
ответ дан ishandutta2007 16 August 2018 в 04:06
поделиться

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

By комбинируя 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 - самый быстрый способ получить подсчитывать и хранить их все.

31
ответ дан JBecker 16 August 2018 в 04:06
поделиться
  • 1
    Преимущество этого, vs table, заключается в том, что он дает результат в более удобном для использования формате? благодаря – Heather Stark 31 January 2013 в 15:54
  • 2
    @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), что иногда полезно. – JBecker 22 April 2013 в 21:42
  • 3
    с помощью microbenchmark, кажется, что table быстрее when the vector is long (я пробовал 100000), но немного дольше, когда он короче (я пробовал 1000) – clemlaflemme 21 June 2016 в 16:54
  • 4
    Это будет очень медленно, если у вас много цифр. – skan 13 December 2016 в 20:46

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

x <- 23
length(subset(numbers, numbers==x))
8
ответ дан JD Long 16 August 2018 в 04:06
поделиться

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

length(which(numbers==x))

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

table(numbers)
45
ответ дан Jesse 16 August 2018 в 04:06
поделиться
  • 1
    table(numbers) собирается сделать гораздо больше работы, чем самое простое решение, sum(numbers==x), потому что он также будет вычислять количество всех остальных номеров в списке. – Ken Williams 18 December 2009 в 20:41
  • 2
    проблема с таблицей заключается в том, что ее сложнее включить в более сложное исчисление, например, используя apply () на dataframes – skan 2 December 2015 в 13:16

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

length(which(numbers == 4))
6
ответ дан Matthew 16 August 2018 в 04:06
поделиться

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

32
ответ дан MichaelChirico 16 August 2018 в 04:06
поделиться

Использование таблицы, но без сравнения с 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
ответ дан pomber 16 August 2018 в 04:06
поделиться

Существует стандартная функция в R для этого

tabulate(numbers)

16
ответ дан Sergej Andrejev 16 August 2018 в 04:06
поделиться
  • 1
    Недостатком tabulate является то, что вы не можете иметь дело с нулевым и отрицательным числом. – omar 1 June 2016 в 15:55
  • 2
    Но вы можете иметь дело с нулевыми экземплярами заданного числа, которые другие решения не обрабатывают – Dodgie 31 January 2017 в 01:26
Другие вопросы по тегам:

Похожие вопросы: