【问题标题】:Replace multiple strings of text in a large dataframe in r在r中替换大型数据框中的多个文本字符串
【发布时间】:2015-04-18 22:33:23
【问题描述】:

我一直在尝试使用 gsub 将标识符键替换为边缘列表中的简单整数。边缘列表由个人和他们的连接列表(个人可变长度)组成。不幸的是,由于我的数据集超过 300K 行(因此需要 300K+ 搜索和替换操作),因此迭代地运行它需要将近一周的时间。当前代码能够产生所需的输出,但我正在尝试找到一种更有效的方法。有谁知道产生类似输出的更好方法?我当前的代码、一些假设的示例数据和示例输出如下:

样本数据:

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

【问题讨论】:

  • 你能详细说明你想替换什么吗?也尝试这样做apply(data,1, function(x) gsub("to.replace", "replace.with", x))
  • 根据您想要的输出,fixed=T 或 perl=T 可能会解决问题。我通常在 15 分钟内运行 400k 行和 7000 个模式
  • 请分享dput(head(yourDataFrame)) 的输出以及该小样本所需的输出。
  • 所以我要替换的是带有键值(又名 1:length(dataset))的人的 ID。这里的具体困难是我需要搜索和替换 300K+ 的值。

标签: r replace network-programming dataframe gsub


【解决方案1】:

不是明确的代码来解决你的问题,而是我会使用的策略。

如果我没看错的话,Person 是唯一标识符,Connection_list 是人与人之间的界限。如果您的值是因子,并且如果您需要数值以在分析流中进一步计算,则实际上不需要显式转换为整数,您可以使用因子整数值。

首先,我会将 Connection_list 转换为多个列,例如:Split column into multiple columns R。

然后,完成后,您的列被识别为包含因子值,

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

您应该能够使用类似于as.numeric(as.character(f)) 的方式从这些因子中检索数值。

【讨论】:

  • 这种方法的唯一问题是每个人有不同数量的边缘,其中一些边缘甚至没有连接,而其他边缘可能有数百个。
【解决方案2】:

我最终以一种迂回的方式解决了这个问题。因为每个用户都有不同长度的朋友,我使用dplyr 包来拆分每一行,并对每一行应用一个拆分功能(使用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)

【讨论】:

    猜你喜欢
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 2014-08-29
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    相关资源
    最近更新 更多