Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 用另一个数据帧中的相应项替换所有数据帧单元格中的字符串_R_Replace - Fatal编程技术网

R 用另一个数据帧中的相应项替换所有数据帧单元格中的字符串

R 用另一个数据帧中的相应项替换所有数据帧单元格中的字符串,r,replace,R,Replace,我有一个数据帧,在一个数据帧的一个单元格中有不同数目的名称,我想用另一个数据帧的相应数目来替换它。之后,我想继续计算平均值和最大值,但这不是我的问题的一部分 df_with_names <-read.table(text=" id names 1 AA,BB 2 AA,CC,DD 3 BB,CC 4 AA,BB,CC,DD ",header=TRUE,sep="") 从这里我知道如何前进,但我不知道如何到达那里 我试图将循环中每一行的名称分离成一个数据帧,然后替换这些名称,但总是无法用名

我有一个数据帧,在一个数据帧的一个单元格中有不同数目的名称,我想用另一个数据帧的相应数目来替换它。之后,我想继续计算平均值和最大值,但这不是我的问题的一部分

df_with_names <-read.table(text="
id names
1 AA,BB
2 AA,CC,DD
3 BB,CC
4 AA,BB,CC,DD
",header=TRUE,sep="")
从这里我知道如何前进,但我不知道如何到达那里


我试图将循环中每一行的名称分离成一个数据帧,然后替换这些名称,但总是无法用名称获得
df\u的正确列。过了一会儿,我怀疑
replace()
是否是我正在寻找的函数。谁能帮忙?

注意:确保两个数据帧都是按id排序的,否则您可能会看到意外的结果

listing <- df_with_names
listing <- strsplit(as.character(listing$names),",")

col1 <- lapply(listing, function(x) df_names[(df_names[[1]] %in% x),2])
col2 <- lapply(listing, function(x) df_names[(df_names[[1]] %in% x),3])

col1 <- unlist(lapply(col1, paste0, collapse = ","))
col2 <- unlist(lapply(col2, paste0, collapse = ","))

data.frame(number_1 = col1, number_2 = col2 )

     number_1    number_2
1       20,12       30,14
2    20,13,14    30,29,27
3       12,13       14,29
4 20,12,13,14 30,14,29,27
列表
上述方法首先沿第一个
数据表中的逗号拆分名称,然后将其与第二个表连接(在适当设置键后),并用逗号将所有结果列折叠回去。

另一个多功能表:

data2match <- strsplit(df_with_names$names, ',')

lookup <- function(lookfor, in_df, return_col, search_col=1) {
  in_df[, return_col][match(lookfor, in_df[, search_col])]
}

output <- 
  # for each number_x column....
  sapply(names(df_names)[-1],
         function(y) {
           # for each set of names
           sapply(data2match,
                  function(x) paste(sapply(x, lookup, df_names, 
                                  y, USE.NAMES=F), collapse=','))
         })

data.frame(id=1:nrow(output), output)
我不喜欢“names”或“name”这样的名字,所以我选择了“nam”:


(我很惊讶scan(text=…一个因子变量实际上成功了。)

我认为实际上值得你用_名称重新排列你的
dfu数据集,使事情更加直截了当:

spl <- strsplit(as.character(df_with_names$names), ",")
df_with_names <- data.frame(
  id=rep(df_with_names$id, sapply(spl, length)),
  name=unlist(spl)
)

#   id name
#1   1   AA
#2   1   BB
#3   2   AA
#4   2   CC
#5   2   DD
#6   3   BB
#7   3   CC
#8   4   AA
#9   4   BB
#10  4   CC
#11  4   DD

aggregate(
  . ~ id,
  data=merge(df_with_names, df_names, by="name")[-1],
  FUN=function(x) paste(x,collapse=",")
)

#  id    number_1    number_2
#1  1       20,12       30,14
#2  2    20,13,14    30,29,27
#3  3       12,13       14,29
#4  4 20,12,13,14 30,14,29,27
spl另一种方法:

df3 = data.frame(id=df1$id, 
                 number_1=as.character(df1$names), 
                 number_2=as.character(df1$names), stringsAsFactors=FALSE)

for(n1 in 1:nrow(df3))
    for(n2 in 1:nrow(df2)){
            df3[n1,2] = sub(df2[n2,1],df2[n2,2], df3[n1,2] )   
            df3[n1,3] = sub(df2[n2,1],df2[n2,3], df3[n1,3] )   
    }

df3
#  id    number_1    number_2
#1  1       20,12       30,14
#2  2    20,13,14    30,29,27
#3  3       12,13       14,29
#4  4 20,12,13,14 30,14,29,27

+1用于该查找函数。使我想起Excel的查找函数。这看起来很短,速度也非常快。尽管我不明白这里发生了什么,因为除了排序之外。@user3621464尝试单独运行每个片段-如果某些部分不清楚,请随时询问它。对于具有数字。运行得很好-我唯一不喜欢的是我必须自己编写包含数字的变量(
number\u 1,number\u 2
)的每个名称。如果名称随数据集的不同而变化,或者如果名称很多,您需要额外的努力。@user3621464-您可以绕过这个问题-请参阅我的编辑。
data2match <- strsplit(df_with_names$names, ',')

lookup <- function(lookfor, in_df, return_col, search_col=1) {
  in_df[, return_col][match(lookfor, in_df[, search_col])]
}

output <- 
  # for each number_x column....
  sapply(names(df_names)[-1],
         function(y) {
           # for each set of names
           sapply(data2match,
                  function(x) paste(sapply(x, lookup, df_names, 
                                  y, USE.NAMES=F), collapse=','))
         })

data.frame(id=1:nrow(output), output)
  id    number_1    number_2
1  1       20,12       30,14
2  2    20,13,14    30,29,27
3  3       12,13       14,29
4  4 20,12,13,14 30,14,29,27
 do.call( rbind,    # reassembles the individual lists
    apply(df_with_names, 1,   # for each row in df_with_names
          function(x)  lapply(   #  lapply(..., paste) to each column
             # Next line will read each comma separated value and 
             # and match to rows of df_names[] and return cols 2:3
               df_names[ df_names$nam %in% scan(text=x[2], what="", sep=",") ,
                       2:3, drop=FALSE] ,   # construct packet of text digits
                                paste0, collapse=",") ) )


     number_1      number_2     
[1,] "20,12"       "30,14"      
[2,] "20,13,14"    "30,29,27"   
[3,] "12,13"       "14,29"      
[4,] "20,12,13,14" "30,14,29,27"
spl <- strsplit(as.character(df_with_names$names), ",")
df_with_names <- data.frame(
  id=rep(df_with_names$id, sapply(spl, length)),
  name=unlist(spl)
)

#   id name
#1   1   AA
#2   1   BB
#3   2   AA
#4   2   CC
#5   2   DD
#6   3   BB
#7   3   CC
#8   4   AA
#9   4   BB
#10  4   CC
#11  4   DD

aggregate(
  . ~ id,
  data=merge(df_with_names, df_names, by="name")[-1],
  FUN=function(x) paste(x,collapse=",")
)

#  id    number_1    number_2
#1  1       20,12       30,14
#2  2    20,13,14    30,29,27
#3  3       12,13       14,29
#4  4 20,12,13,14 30,14,29,27
df3 = data.frame(id=df1$id, 
                 number_1=as.character(df1$names), 
                 number_2=as.character(df1$names), stringsAsFactors=FALSE)

for(n1 in 1:nrow(df3))
    for(n2 in 1:nrow(df2)){
            df3[n1,2] = sub(df2[n2,1],df2[n2,2], df3[n1,2] )   
            df3[n1,3] = sub(df2[n2,1],df2[n2,3], df3[n1,3] )   
    }

df3
#  id    number_1    number_2
#1  1       20,12       30,14
#2  2    20,13,14    30,29,27
#3  3       12,13       14,29
#4  4 20,12,13,14 30,14,29,27