【问题标题】:mapply giving non-numeric argument to binary operator error in R在R中为二元运算符错误提供非数字参数
【发布时间】:2020-02-05 05:06:51
【问题描述】:

我正在尝试生成一个变量来标记家庭名册中受访者与其父母之间难以置信的年龄差异。 mapply() 在“二元运算符的非数字参数”上给出错误,而当我仅在两列上应用该函数时,我没有收到此错误。很感谢任何形式的帮助。下面,我试图做一个可重现的例子。


# Variables
respbirth <- c(1974, 1950, 1990, 1980 ) 
B1010_1 <- c(1950, 1960, 1960, 1979 ) 
B1040_1 <- c(3,3,3,3)
B1010_2 <- c(1974, NA, NA, 1975 ) 
B1040_2 <- c(3,1,3,3)

# Data frame
df <- data.frame(respbirth, B1010_1, B1040_1, B1010_2, B1040_2 ) 
df

# Generate empty variable for flaging cases
df$flag_parent <- FALSE

## Generate a function flagging implausible differences using year of birth
attach(df)  # the function doesnt work without this for some reason
imp.parent <- function(data=df,parentAge=B1010_1,relationship=B1040_1) {
  df$flag_parent <- with(df, ((respbirth-parentAge)<18) & (relationship==3))
return(df)
}

# Test
df <- imp.parent(parentAge=B1010_1,relationship=B1040_1)

# Apply this function to all columns
parentAge <- c(paste0("B1010_",1:19, sep=""))
relationship <- c(paste0("B1040_",1:19, sep=""))
mapply(imp.parent, parentAge, relationship )

【问题讨论】:

  • 这里为什么有library(tidyverse)?这里的一切都是基础。
  • imp.parent 没有保存任何更改,它正在返回一个数字向量。如果您打算让它在框架中添加 flag_parent 然后返回框架,您需要这样做(例如,dfreturn(df) 作为函数的最后一行) .
  • 您最初将logical 值分配给flag_parent,但随后在函数中分配numeric。然后你抱怨没有分配TRUE。我真的很困惑。
  • 感谢@r2evans,第一个问题通过将函数分配给函数外的 df 得到解决——函数内的 return(df) 不起作用。我现在删除了 as.numeric() ,这是我在试验时添加的。但实际上无论哪种方式都有效,mapply() 出现同样的错误。
  • 奇怪,你的函数的编写方式,这不应该工作:df 应该被一个向量覆盖,丢失所有的帧。 imp.parent 的返回值应该是其主体中最后一个表达式的返回值,在本例中为 with(df, (...))。即使该值被存储为df$ 中的列(预先存在的或新的)并不重要,&lt;- 右侧的值是一个向量,这是函数调用返回的值。或者也许我错过了一些东西。 (你之前是 attaching 它,由于这样的原因,这通常是不好的。)

标签: r mapply


【解决方案1】:

目前,您的mapply 尝试存在许多问题,包括参数类型、函数调用、返回值等。为避免列出这些问题,请考虑以下重构代码。

# Generate a function flagging implausible differences using year of birth
imp.parent <- function(parentAge, relationship, data=df) {    
  ((df$respbirth - df[[parentAge]]) < 18) & (df[[relationship]] == 3)  
}

# Apply this function to all columns
parentAge <- c(paste0("B1010_", 1:2))
relationship <- c(paste0("B1040_", 1:2))

# Assign columns True/False
df[paste0("false_flag_", 1:2)] <- mapply(imp.parent, parentAge, relationship )

df    
#   respbirth B1010_1 B1040_1 B1010_2 B1040_2 false_flag_1 false_flag_2
# 1      1974    1950       3    1974       3        FALSE         TRUE
# 2      1950    1960       3      NA       1         TRUE        FALSE
# 3      1990    1960       3      NA       3        FALSE           NA
# 4      1980    1979       3    1975       3         TRUE         TRUE

事实上,你甚至需要 mapply(隐藏循环)! R 可以计算跨等长数据块的逻辑条件,用于列块的矢量化分配:

# Apply this function to all columns
parentAge <- c(paste0("B1010_", 1:2))
relationship <- c(paste0("B1040_", 1:2))

# NOTICE USE OF `[` (NOT `[[`)
df[paste0("false_flag_", 1:2)] <- ((df$respbirth - df[parentAge]) < 18) & (df[relationship] == 3) 

df    
#   respbirth B1010_1 B1040_1 B1010_2 B1040_2 false_flag_1 false_flag_2
# 1      1974    1950       3    1974       3        FALSE         TRUE
# 2      1950    1960       3      NA       1         TRUE        FALSE
# 3      1990    1960       3      NA       3        FALSE           NA
# 4      1980    1979       3    1975       3         TRUE         TRUE

Online Demo

【讨论】:

  • 这太好了,非常感谢!我有很多东西要学,处理数据类型感觉像是最棘手的事情之一。在 Stata 中,我会使用 for 循环和局部变量来完成此操作,但我会花费数小时在 R 中做同样的事情。这是一个非常不同的世界。
  • 很高兴听到并乐于提供帮助!
  • 我接受了答案,无法投票 - 还不够受欢迎 :) 再次感谢 Parfait,你让我开心!
猜你喜欢
  • 2016-11-15
  • 1970-01-01
  • 2019-05-03
  • 2016-11-14
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多