Dataframe基于其他列创建新列

rag*_*esz 10 r apply dataframe

我有一个数据帧:

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
Run Code Online (Sandbox Code Playgroud)

我想基于现有列创建一个新列.像这样的东西:

if (df[['a']] == df[['b']]) {
  df[['c']] <- df[['a']] + df[['b']]
} else {
  df[['c']] <- df[['b']] - df[['a']]
}
Run Code Online (Sandbox Code Playgroud)

问题是if只检查第一行的条件...如果我从上面的if语句创建一个函数然后我使用apply()(或mapply()...),它是相同的.

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

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

我希望在R中有类似的东西.所以结果看起来像这样:

    a    b    c
1   1    1    2
2   2   20   18
3   3    3    6
4   4    4    8
5   5   50   45
Run Code Online (Sandbox Code Playgroud)

akr*_*run 22

一个选项是ifelse矢量化版本if/else.如果我们为每一行执行此操作if/else,那么OP的pandas post中显示的可以在for循环中完成lapply/sapply,但是这样做效率很低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
Run Code Online (Sandbox Code Playgroud)

这可以用其他方式写成

df$c <- with(df, ifelse(a==b, a+b, b-a))
Run Code Online (Sandbox Code Playgroud)

在原始数据集中创建"c"列


由于OP想在一个类似的选项R使用if/else

df$c <- apply(df, 1, FUN = function(x) if(x[1]==x[2]) x[1]+x[2] else x[2]-x[1])
Run Code Online (Sandbox Code Playgroud)

  • @ragesz当矢量化解决方案可用时,使用慢的"apply()"循环是一个坏主意.不应该使用[特定类型的命令来解决问题](http://meta.stackexchange.com/a/66378).相反,了解哪种方法适用于哪种情况非常重要.本答案中的矢量化解决方案显示了解决R中问题的正确方法. (2认同)

lmo*_*lmo 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
Run Code Online (Sandbox Code Playgroud)

这个想法是根据测试打开或关闭"减号"操作符a==b.


Sot*_*tos 5

如果您想要一个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
Run Code Online (Sandbox Code Playgroud)


zx8*_*754 5

使用 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
Run Code Online (Sandbox Code Playgroud)