【问题标题】:Assigning data frame name to all rows in a column将数据框名称分配给列中的所有行
【发布时间】:2018-10-16 09:41:33
【问题描述】:

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

虚拟数据:

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 中直接创建此列?

【问题讨论】:

  • 看看dplyr::bind_rows().id 参数。你可以试试这个:bind_rows(your_list, .id = "ref").

标签: r


【解决方案1】:

使用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

【讨论】:

  • 我更喜欢基础版。更少的输入和更少的依赖。
  • 感谢您的回复。然而,对我来说,当我在数据框列表上使用 lapply 时,“ref”列仅包含值 'x[[i]]'
  • @coffeinjunky 正如我在第一行中所说:“我想为列表中的每个数据框将数据框名称添加到列中的所有行中”,如果不清楚,抱歉。
【解决方案2】:

原因是我稍后要 rbind 多个数据帧,并且 我希望能够过滤值来自哪个数据框。

然后只需将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

【讨论】:

    猜你喜欢
    • 2012-08-14
    • 1970-01-01
    • 2021-01-14
    • 1970-01-01
    • 2014-11-03
    • 2021-03-28
    • 2023-03-04
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多