Dataframe基于其他列创建新列

时间:2016-08-26 11:33:19

标签: r dataframe apply

我有一个数据框:

df <- data.frame('a'=c(1,2,3,4,5), 'b'=c(1,20,3,4,50))
df
    a    b
1   1    1
2   2   20
3   3    3
4   4    4
5   5   50

我想基于现有列创建一个新列。像这样:

if (df[['a']] == df[['b']]) {
  df[['c']] <- df[['a']] + df[['b']]
} else {
  df[['c']] <- df[['b']] - df[['a']]
}

问题是if条件仅针对第一行进行检查...如果我从上面的if语句创建函数,那么我使用apply()(或{{ 1}} ...),它是一样的。

在Python / pandas中我可以使用它:

mapply()

我想在R中有类似的东西。所以结果应该是这样的:

df['c'] = df[['a', 'b']].apply(lambda x: x['a'] + x['b'] if (x['a'] == x['b']) \
    else x['b'] - x['a'], axis=1)

5 个答案:

答案 0 :(得分:22)

一个选项是ifelse,它是if/else的矢量化版本。如果我们为每一行执行此操作,那么OP的pandas帖子中显示的if/else可以在for循环或lapply/sapply中完成,但这在{{1}中效率低下}}

R

这可以用其他方式写成

df <- transform(df, c= ifelse(a==b, a+b, b-a))
df
#  a  b  c
#1 1  1  2
#2 2 20 18
#3 3  3  6
#4 4  4  8
#5 5 50 45

在原始数据集中创建“c”列

由于OP希望使用df$c <- with(df, ifelse(a==b, a+b, b-a))

R中使用类似的选项
if/else

答案 1 :(得分:7)

这是一个稍微混乱的代数方法:

df$c <- with(df, b + ((-1)^((a==b)+1) * a))

df
  a  b  c
1 1  1  2
2 2 20 18
3 3  3  6
4 4  4  8
5 5 50 45

我们的想法是根据测试a==b打开或关闭“减号”运算符。

答案 2 :(得分:4)

apply

的解决方案
myFunction <- function(x){
  a <- x[1]
  b <- x[2]
  #further values ignored (if there are more than 2 columns)
  value <- if(a==b) a + b else b - a
  #or more complicated stuff
  return(value)
}

df$c <- apply(df, 1, myFunction)

答案 3 :(得分:4)

如果你想要一个apply方法,那么使用mapply的另一种方法是创建一个函数并应用它,

fun1 <- function(x, y) if (x == y) {x + y} else {y-x}
df$c <- mapply(fun1, df$a, df$b)
df
#  a  b  c
#1 1  1  2
#2 2 20 18
#3 3  3  6
#4 4  4  8
#5 5 50 45

答案 4 :(得分:4)

使用dplyr包:

library(dplyr)

df <- df %>% 
  mutate(c = if_else(a == b, a + b, b - a))

df
#   a  b  c
# 1 1  1  2
# 2 2 20 18
# 3 3  3  6
# 4 4  4  8
# 5 5 50 45