【问题标题】:R - Why does sapply return lists within this dataframe when searching for values in another dataframe?R - 为什么 sapply 在另一个数据框中搜索值时返回此数据框中的列表?
【发布时间】:2016-04-11 13:34:25
【问题描述】:

我有以下两个 2 data.frames:

df1

structure(list(thread_id = c(1L, 1L, 2L, 2L, 2L, 2L), course_week = c(1, 
1, 1, 1, 1, 1), user_id = c(1237305, 3001241, 1237305, 1237305, 
4455134, 4398594), post_id_unique = c("1-NA", "1-post-1", "2-NA", 
"2-post-2", "2-post-2", "2-post-2"), to = list(NULL, 1L, NULL, 
    2L, 2L, 2L)), .Names = c("thread_id", "course_week", "user_id", 
"post_id_unique", "to"), row.names = c(NA, 6L), class = "data.frame")

df2

structure(list(thread_id = c(1L, 1L, 2L, 2L, 2L, 2L), course_week = c(1, 
1, 1, 1, 1, 1), user_id = c(1237305, 3001241, 1237305, 1237305, 
4455134, 4398594), post_id_unique = c("1-post-1", "1-post-1125", 
"2-post-2", "2-post-3", "2-post-43", "2-post-54")), .Names = c("thread_id", 
"course_week", "user_id", "post_id_unique"), row.names = c(NA, 
6L), class = "data.frame")

我正在尝试将 df1$to 替换为 df2$user_id 中与两个文件中的 $post_id_unique 列匹配的值。

我为它编写了以下代码:

from <- as.list(df1$post_id_unique)
replace <- function(i){if(grepl("NA",i)!=TRUE) {df2[df2$post_id_unique==i,1]}}
df1$to <- sapply(from, replace)

这几乎可以完美地工作...除了 df1$to 中的每个值都是一个列表而不是数字或字符向量:

'data.frame':   6 obs. of  5 variables:
 $ thread_id     : int  1 1 2 2 2 2
 $ course_week   : num  1 1 1 1 1 1
 $ user_id       : num  1237305 3001241 1237305 1237305 4455134 ...
 $ post_id_unique: chr  "1-NA" "1-post-1" "2-NA" "2-post-2" ...
 $ to            :List of 6
  ..$ : NULL
  ..$ : int 1
  ..$ : NULL
  ..$ : int 2
  ..$ : int 2
  ..$ : int 2

为什么我的原始代码会在数据框中创建列表?我怎样才能将它们取消列出?或者一开始就避开它们。

我知道这类似于 merge(),但出于学习和其他原因,我对这样做很感兴趣。

【问题讨论】:

  • 您应该在reproducible format(最好是dput)中包含样本数据。听起来你只想要一个merge()。您应该为问题数据提供所需的输出。
  • 感谢@MrFlick 的提示。我已经尝试过合并函数,它返回的 data.frame 的行数比原始 DF 少(我猜是因为有重复的值)。除此之外,我对学习如何使用 sapply 很感兴趣。你认为它没有效率/有效吗?

标签: r dataframe sapply


【解决方案1】:

“问题”是有时您的replace() 函数不返回值(当i 值包含“NA”时)。由于sapply 总是返回一个与输入长度相同的对象,因此该函数返回 NULL 值。 NULL 不能放在简单的向量中,因此 sapply 的结果被强制转换为列表。您可以通过返回 NA 而不是什么都没有来解决此问题

replace <- function(i){if(grepl("NA",i)!=TRUE) {df2[df2$post_id_unique==i,1]} else {NA}}

但实际上看起来您正在执行基本的左合并操作。基本语法是

merge(df1, df2, by="post_id_unique", all.x=T)

【讨论】:

  • 你是对的,这是一个基本的左合并操作,这样解决它是一个更好的方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 2022-11-27
  • 1970-01-01
相关资源
最近更新 更多