Подсчет пар элементов, связанных по значению столбца

Я пытаюсь решить эту проблему в R. У меня есть такие данные:

item   id
1      500
2      500
2      600
2      700
3      500
3      600

data.frame(item = c(1, 2, 2, 2, 3, 3),
           id = c(500, 500, 600, 700, 500, 600))

И я хочу подсчитать, сколько раз пара элементов связана с одним и тем же идентификатором. Итак, я хочу, чтобы этот вывод:

item1    item2    count
    1        2        1
    2        3        2
    1        3        2

Я пытался подойти к этому с помощью таких команд, как:

x_agg = aggregate(x, by=list(x$id), c)

а потом

x_agg_id = lapply(x_agg$item, unique)

думая, что затем я мог бы подсчитать появление каждого элемента. Но функция by, кажется, создает объект списков, которым я не знаю, как манипулировать. Я надеюсь, что есть более простой способ....


person Harry Palmer    schedule 22.08.2012    source источник


Ответы (2)


# your data
df<-read.table(text="item   id
1      500
2      500
2      600
2      700
3      500
3      600",header=TRUE)


library(tnet)
item_item<-projecting_tm(df, method="sum")
names(item_item)<-c("item1","item2","count")

item_item

  #item1 item2 count
#1     1     2     1
#2     1     3     1
#3     2     1     1
#4     2     3     2
#5     3     1     1
#6     3     2     2

ИЗМЕНИТЬ

сколько у тебя идентификаторов и предметов? вы всегда можете переименовать вещи. например

numberitems<-length(unique(df$id))+9000
items<-data.frame(item=unique(df$item),newitems=c(9000:(numberitems-1)))
numberids<-length(unique(df$id))+1000
ids<-data.frame(id=unique(df$id),newids=c(1000:(numberids-1)))
newdf<-merge(df,items,by="item")
newdf<-merge(newdf,ids,by="id")
DF<-data.frame(item=newdf$newitems,id=newdf$newids)

library(tnet)
item_item<-projecting_tm(DF, method="sum")
names(item_item)<-c("item1","item2","count")

затем объедините исходные имена после этого....

person user1317221_G    schedule 22.08.2012
comment
это идеально спасибо! и этот пакет «tnet» может быть очень полезен для других вещей, которые я буду делать! - person Harry Palmer; 22.08.2012
comment
о боже - проблема. некоторые из моих элементов / идентификаторов имеют очень большие значения (10 или 11 цифр), и кажется, что функция projecting_tm выдает ошибку при работе с числами, превышающими 9 цифр. Есть ли более общее решение? Возможно, тот, который позволит мне использовать строки вместо целых чисел? - person Harry Palmer; 22.08.2012
comment
@HarryPalmer, тебя волнует порядок предметов? Например, является ли комбинация 1 и 2 для item1 и item2 такой же, как комбинация 2 и 1 для item1 и item2? - person A5C1D2H2I1M1N2O1R2T1; 22.08.2012
comment
Привет, mrdwab, нет, меня не волнует порядок элементов. Большое спасибо за ваши подробные ответы, я собираюсь попробовать их завтра и сообщить вам, как это работает! - person Harry Palmer; 23.08.2012

Я предлагаю этот подход, потому что из вашего примера неясно, является ли ответ от @user1317221_G именно тем, что вы ищете. В этом примере комбинация 2 3 подсчитывается 4 раза, дважды для item1 = 2, item2 = 3 и дважды для item1 = 3, item2 = 2.

Я бы попробовал функцию combn. Он не дает вам в точности тот результат, который вы ищете, но, вероятно, может быть адаптирован для этой цели.

Вот пример.

  1. Напишите базовую функцию, которая будет генерировать комбинации всего, что мы ей даем.

    myfun = function(x) { apply(combn(x, 2), 2, paste, sep="", collapse="") }
    
  2. split() столбец item ваших данных с помощью id и используйте lapply для создания комбинаций в пределах этого id.

    temp = split(df$item, df$id)
    # Drop any list items that have only one value--combn won't work there!
    temp = temp[-(which(sapply(temp,function(x) length(x) == 1),
                        arr.ind=TRUE))]
    temp1 = lapply(temp, function(x) myfun(unique(x)))
    
  3. Используйте unlist, а затем table, чтобы занести в таблицу частоты каждой комбинации.

    table(unlist(temp1))
    # 
    # 12 13 23 
    #  1  1  2
    

Вы можете получить data.frame, если хотите.

data.frame(table(unlist(temp)))
#   Var1 Freq
# 1   12    1
# 2   13    1
# 3   23    2

Обновлять

Как уже упоминалось, приложив немного больше усилий, вы можете использовать этот метод, чтобы получить желаемый результат:

myfun = function(x) { apply(combn(x, 2), 2, paste, sep="", collapse=",") }
temp = split(df$item, df$id)
temp = temp[-(which(sapply(temp,function(x) length(x) == 1),
                    arr.ind=TRUE))]
temp1 = lapply(temp, function(x) myfun(unique(x)))
temp1 = data.frame(table(unlist(temp1)))
OUT = data.frame(do.call(rbind, 
                         strsplit(as.character(temp1$Var1), ",")),
                 temp1$Freq)
names(OUT) = c("item1", "item2", "count")
OUT
#   item1 item2 count
# 1     1     2     1
# 2     1     3     1
# 3     2     3     2
person A5C1D2H2I1M1N2O1R2T1    schedule 22.08.2012
comment
Хм. Я получаю это сообщение об ошибке после того, как › temp1 = lapply(temp, function(x) myfun(unique(x))) : Предупреждающее сообщение: In combn(x, 2): NA введены принудительной ошибкой в ​​apply(combn(x, 2) ), 2, вставить, sep = , свернуть = ,) : ошибка при оценке аргумента «X» при выборе метода для функции «применить»: ошибка в seq_len(x): аргумент должен быть приведен к неотрицательному целому числу - person Harry Palmer; 23.08.2012
comment
@HarryPalmer, не могли бы вы dput несколько строк данных, с которыми вы работаете, предпочтительно строки, в которых вы чувствуете, что сталкиваетесь с ошибками? - person A5C1D2H2I1M1N2O1R2T1; 23.08.2012
comment
Я получаю ту же ошибку, работающую только на этих 15 строках. Может быть, размер целых чисел? structure(list(id = c(909128296, 5012895441, 979322531, 1475171536, 5272803586, 5377444521, 6652900376, 497636221, 9708548701, 5695003406, 996433791, 5317141656, 7197368271, 423477811, 5953151441), isbn = c(9781405910248, 9781405910248, 9781405910248, 9781405910248 , 9780141906201, 9781405910248, 9781405910248, 9780141959948, 9780141910970, 9780141904443, 9781405910248, 9781405910248, 9781405910248, 9780141967899, 9780141965635)), .Names = c(id, isbn), row.names = c(NA, 15L), class = data. Рамка) - person Harry Palmer; 23.08.2012