2015-04-18 2 views
1

Я пытаюсь использовать gsub для замены ключей идентификатора простыми целыми числами в edgelist. Edgelist состоит из отдельных лиц и список их связей (переменная длина по отдельности). К сожалению, поскольку мой набор данных содержит более 300 тыс. Строк (для этого требуются операции поиска и замены 300 КБ +), для его запуска итеративно потребуется почти неделя, чтобы пройти. В настоящее время код способен вывести желаемый результат, но я пытаюсь найти более эффективный метод. Кто-нибудь знает лучший метод для создания аналогичной продукции? Мой текущий код, некоторые гипотетические данные выборки, а выходной образец ниже:Замените несколько строк текста в большом фрейме данных в r

Образец данных:

Person Connection_list 
ENJAK IDFJA, FDAKD, AODMK 
JBJDF KJDFA 
LAFMD JBJDF, KAOJD, ENJAK,FKJSE,IDFJA, AKSKE, FNAFJ, KJDFA, ATNFN, ADOFA, ODIJA, AODMK, NAGJA, NFAKD, FDAKD, KDSFN 
ADOFA JDFKA, KAOJD, NAGJA 
KJDFA ENJAK, ATNFN, NFAKD, ADOFA, AODMK, JDFKA, LAFMD, ODIJA, FNAFJ, KDSFN, JBJDF, FJKAS, FKJSE, AKSKE, NAGJA 
IDFJA AKSKE, KJDFA, FJKAS, ADOFA 
KDSFN KAOJD, ADOFA, AKSKE, FDAKD, NFAKD, FKJSE, NAGJA, JDFKA, ODIJA, FJKAS, ATNFN, JBJDF, FNAFJ, KJDFA, LAFMD, ENJAK 
AKSKE ADOFA, ODIJA, KAOJD, JBJDF, ENJAK, AODMK, FDAKD, IDFJA, NAGJA, KJDFA 
NAGJA KAOJD, AKSKE 
ODIJA ADOFA, FDAKD, FKJSE, ATNFN, IDFJA, NAGJA, KAOJD 
FKJSE JBJDF, NAGJA, KDSFN, KAOJD, LAFMD, KJDFA, NFAKD, FDAKD, ENJAK, ATNFN, FNAFJ, ODIJA, ADOFA, AODMK, FJKAS, AKSKE, IDFJA 
FDAKD ADOFA, ODIJA, FKJSE, NAGJA, NFAKD, KJDFA, JBJDF, ATNFN, AODMK, AKSKE, KDSFN, JDFKA, LAFMD 
NFAKD ADOFA, KJDFA, AKSKE, KDSFN, FJKAS, JBJDF, JDFKA 
FJKAS FKJSE, AKSKE, FDAKD, NAGJA, ADOFA, ENJAK, FNAFJ, KDSFN, NFAKD, ATNFN, AODMK, KAOJD, JBJDF, JDFKA, LAFMD, IDFJA 
JDFKA AKSKE, KJDFA, IDFJA 
ATNFN AODMK, IDFJA, AKSKE 
KAOJD ENJAK, FJKAS, FKJSE, AKSKE, NFAKD, LAFMD, JDFKA, KDSFN, ODIJA 
AODMK AKSKE, FNAFJ, KAOJD, JDFKA, LAFMD, FDAKD, KDSFN, ENJAK, FJKAS, JBJDF, FKJSE, IDFJA, ATNFN 
FNAFJ JBJDF, ADOFA, NFAKD, ODIJA, KAOJD, FKJSE, LAFMD, AKSKE, KDSFN, IDFJA, FNAFJ, ENJAK 

Текущий код:

for (i in 1:dim(data)[1]){ 
    data$key[i] <- i 
    data[,2] <- gsub(data[i,1],as.character(i),data[,2]) 
} 

Желаемая/выходной ток:

key Person Connection_list 
1 ENJAK 6,12,1,18 
2 JBJDF 5 
3 LAFMD 2,17,3,1,11,6,8,19,5,16,4,10,18,9,13,12,7 
4 ADOFA 15,17,9,4 
5 KJDFA 1,5,16,13,4,18,15,3,10,19,7,2,14,11,8,9 
6 IDFJA 8,5,14,4,6 
7 KDSFN 17,4,8,12,13,11,9,15,7,10,14,16,2,19,5,3,1 
8 AKSKE 4,10,17,2,1,18,12,6,9,5 
9 NAGJA 17,8 
10 ODIJA 4,12,11,16,6,9,17 
11 FKJSE 2,9,7,17,3,5,13,12,11,1,16,19,10,4,18,14,8,6 
12 FDAKD 4,10,11,9,12,13,5,2,16,18,8,7,15,3 
13 NFAKD 4,5,8,7,14,2,15 
14 FJKAS 11,8,14,12,9,4,1,19,7,13,16,18,17,2,15,3,6 
15 JDFKA 8,5,15,6 
16 ATNFN 16,18,6,8 
17 KAOJD 1,14,11,8,13,3,15,7,10 
18 AODMK 8,19,17,15,3,12,7,1,14,2,11,6,16,18 
19 FNAFJ 2,4,13,10,17,11,3,8,7,6,19,1 
+1

Не могли бы вы рассказать в деталях, что именно вы хотите, чтобы заменить ? попробуйте сделать это 'apply (data, 1, function (x) gsub (" to.replace "," replace.with ", x))' –

+0

В зависимости от вашего желаемого результата либо 'fixed = T', либо' perl = T' может решить проблему. Я обычно запускаю через 400 тыс. Строк и 7000 паттернов за 15 минут. –

+0

Пожалуйста, поделитесь выходом 'dput (head (yourDataFrame))' и желаемым выходом для этого небольшого образца. – A5C1D2H2I1M1N2O1R2T1

ответ

0

В конце концов я решил решить проблему. Поскольку каждый пользователь имел разную длину друзей, я использовал пакет dplyr для разделения каждой строки и применения функции split (с использованием пакета stringr) к каждой строке: создание «длинного» эггелиста, а затем я снова объединил результат первоначальный формат после преобразования списка в их эквиваленты факторов. Код для рекомбинируют довольно сумбурно, и я уверен, что может быть более эффективный способ сделать это, но код выглядит примерно так:

library(dplyr) 
library(stringr) 
# User defined split fuction 
longedge <- function(df){ 
    user <- df$user_id 
    cnx <- df$friends 
    split <- as.data.frame(ifelse(cnx=="",NA,str_split(cnx,", "))) 
    combine <- as.data.frame(cbind(user,split),stringAsFactors=FALSE) 
    colnames(combine) <- c("user_id", "friend") 
    return(combine) 
} 
# Creating long edgelist 
edgelist <- edgelist %>% 
    rowwise() %>% 
    do(longedge(.)) %>% 
    rbind() 
# Convert to number 
edgelist$friend <- as.numeric(as.factor(edgelist$friend)) 

# Create count of No. of connections 
edgelist1 <- edgelist %>% 
    group_by(user_id) %>% 
    summarize(friend_count=n()) 

# Recreate 'wide' connection list 
friend_list <- rep(NA,dim(edgelist1)[1]) 
for (i in 1:dim(edgelist1)[1]){ 
    if(i==1){j<-1} 
    x <- j + edgelist1$friend_count[i] 
    friend_list[i] <- as.character(edgelist$friend[j]) 
    j <- j+1 
    while(j < x){ 
    friend_list[i] <- paste(friend_list[i],edgelist$friend[j],sep=", ") 
    j <- j+1 
    } 
} 

# Recombine 
edgelist1 <- cbind(edgelist1,friend_list) 
0

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

Если я прочитал это правильно, Person является уникальным идентификатором, а Connection_list - вашими краями между людьми. Явное преобразование в целое число действительно не необходимо, если ваши значения являются факторами, и если вам нужны числовые значения для вычислений, которые далее используются в вашем потоке анализа, вы можете использовать значения целочисленных факторов.

Во-первых, я бы преобразовал Connection_list в несколько столбцов, обсужденных здесь, например: Split column into multiple columns R.

Затем, после того, как это будет сделано, и ваши столбцы признаны содержащими значений факторов,

aframe2 <- as.data.frame(lapply(aframe1, factor)) 

Вы должны иметь возможность получить числовые значения из этих факторов, используя что-то вдоль линий as.numeric(as.character(f)).

+0

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

Смежные вопросы