将数据框名称分配给列

时间:2018-05-06 12:28:52

标签: r

我想为列表中的每个数据框添加数据框名称到列中的所有行。

虚拟数据:

test_df <- data.frame(x = 1:5, y = c("a","b","c","d","e"))

我想要最终得到的是:

x    y    ref
1    a    test_df
2    b    test_df
3    c    test_df
4    d    test_df
5    e    test_df

原因是我稍后将对多个数据帧进行rbind,我希望能够过滤值来自哪个数据帧。我尝试了以下方法:

library(dplyr)

test <- function(df) {
  df <- df %>%
    mutate(ref = deparse(substitute(df)))
  return(df)
}

但是这只会在每行中创建一个名为ref的列,其值为“df”。任何有关dplyr的建议都非常感谢。或者有没有办法在rbind-call中直接创建这个列?

2 个答案:

答案 0 :(得分:3)

使用dplyr,试试这个:

library(lazyeval)
test <- function(df) {
   df <- df %>% mutate(ref = expr_label(df))
   return(df)
 }
test(test_df)
  x y       ref
1 a `test_df`
2 b `test_df`
3 c `test_df`
4 d `test_df`
5 e `test_df`

或者,这也有效,但不使用dplyr

test2 <- function(df) {
  df$ref <- deparse(substitute(df))
  return(df)
}
test2(test_df)
  x y     ref
1 1 a test_df
2 2 b test_df
3 3 c test_df
4 4 d test_df
5 5 e test_df

要使这项工作与数据框列表一致,而lapply由于lapply的工作原理而变得更加棘手,但以下解决方法有效:

test_df <- data.frame(x = 1:5, y = c("a","b","c","d","e"))
test_df2 <- data.frame(x = 11:15, y = c("aa","bb","cc","dd","ee"))

在这里,我创建了一个命名的数据帧列表:

dfs <- setNames(list(test_df, test_df2), c("test_df", "test_df2"))
dfs
$test_df
  x y
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e

$test_df2
   x  y
1 11 aa
2 12 bb
3 13 cc
4 14 dd
5 15 ee

现在我改变辅助函数以接受名称作为参数:

test3 <- function(df, nm) {
  df$ref <- nm
  return(df)
}

这里我只将名称传递给lapply,并从我上面定义的命名列表dfs中检索每个数据帧。

lapply(names(dfs), function(x) test3(dfs[[x]], x))
[[1]]
  x y     ref
1 1 a test_df
2 2 b test_df
3 3 c test_df
4 4 d test_df
5 5 e test_df

[[2]]
   x  y      ref
1 11 aa test_df2
2 12 bb test_df2
3 13 cc test_df2
4 14 dd test_df2
5 15 ee test_df2

这不是最优雅的方式,但它有效。

话虽如此,如果您想将数据帧合并为一个数据帧,那么@ markus建议使用bind_rows的内容并不多,如

bind_rows(dfs, .id="ref")
        ref  x  y
1   test_df  1  a
2   test_df  2  b
3   test_df  3  c
4   test_df  4  d
5   test_df  5  e
6  test_df2 11 aa
7  test_df2 12 bb
8  test_df2 13 cc
9  test_df2 14 dd
10 test_df2 15 ee

答案 1 :(得分:1)

  

原因是我将在以后重新绑定多个数据帧   我希望能够过滤值来自哪个数据框。

然后只需将dplyr::bind_rows.id参数一起使用:

library(dplyr)
bind_rows(df_list,.id="name")
# works also : purrr::map_dfr(df_list,identity,.id="name")
# works also : data.table::rbindlist(df_list,idcol="name")

#   name x y
# 1    A 1 a
# 2    A 2 b
# 3    B 1 a
# 4    B 2 b
# 5    C 1 a
# 6    C 2 b

如果您的data.frames已不在列表中,请注意tibble::lst会在将这些元素添加到列表时对其进行命名,例如lst(df_A,df_B,df_C)

您的示例案例因此由bind_rows(lst(test_df),.id="name")

解决

数据

test_df <- data.frame(x = 1:2, y = c("a","b"))
df_list <- setNames(replicate(3,test_df,FALSE),LETTERS[1:3])
# $A
# x y
# 1 1 a
# 2 2 b
# 
# $B
# x y
# 1 1 a
# 2 2 b
# 
# $C
# x y
# 1 1 a
# 2 2 b