【问题标题】:Pandas: Column that is dependent on another valuePandas:依赖于另一个值的列
【发布时间】:2017-05-24 04:28:30
【问题描述】:

我有一个如下所示的 Pandas 数据框:

   col1  col2  col3  col4
0     5     1    11     9
1     2     3    14     7
2     6     5    54     8
3    11     2    67    44
4    23     8     2    23
5     1     5     9     8
6     9     7    45    71

我想制作第 5 列 (col5),它取决于 col1 的值并取其他列之一的值。

这是我想要的外观,但有一些问题。

if col1 < 3:
   col5 == col2
elif col1 < 7 & col1 >= 3:
   col5 == col3
elif col1 >= 7 & col1 < 50:
   col5 == col4

这将产生以下数据框:

   col1  col2  col3  col4  col5
0     5     1    11     9    11
1     2     3    14     7     3
2     6     5    54     8    54
3    11     2    67    44    44
4    23     8     2    23    23
5    97     5     9     8     8
6     9     7    45    71    71

提前感谢,如果您有任何问题,请告诉我

【问题讨论】:

  • 列数和逻辑是固定的吗??
  • 是的,列和逻辑是固定的
  • col1 &gt; 50的逻辑是什么?

标签: python pandas if-statement conditional-statements multiple-columns


【解决方案1】:

您可以使用多个numpy.where,如果没有条件是True (col1 =&gt; 50) 被添加最后一个值1

df['col5'] = np.where(df['col1'] <3, df['col2'], 
             np.where((df['col1'] <7) & (df['col1'] >=3 ), df['col3'], 
             np.where((df['col1'] >=7) & (df['col1'] <50 ), df['col4'], 1))) 
print (df)
   col1  col2  col3  col4  col5
0     5     1    11     9    11
1     2     3    14     7     3
2     6     5    54     8    54
3    11     2    67    44    44
4    23     8     2    23    23
5    97     5     9     8     1
6     9     7    45    71    71

通过更改的值进行编辑:

如果所有值都需要col4 &gt;=7

df['col5'] = np.where(df['col1'] <3, df['col2'], 
             np.where((df['col1'] <7) & (df['col1'] >=3 ), df['col3'], df['col4']))
print (df)
   col1  col2  col3  col4  col5
0     5     1    11     9    11
1     2     3    14     7     3
2     6     5    54     8    54
3    11     2    67    44    44
4    23     8     2    23    23
5    97     5     9     8     8
6     9     7    45    71    71

len(df)=7000 中的时间安排:

In [441]: %timeit df['col51'] = np.where(df['col1'] <3, df['col2'], np.where((df['col1'] <7) & (df['col1'] >=3 ), df['col3'], df['col4']))
The slowest run took 5.31 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 1.25 ms per loop

In [442]: %timeit df["col52"] = df.apply(lambda x: col52(x), axis=1)
1 loop, best of 3: 552 ms per loop

In [443]: %timeit df["col53"] = [col53(c1,c2,c3,c4) for c1,c2,c3,c4 in zip(df.col1,df.col2,df.col3,df.col4)]
100 loops, best of 3: 9.87 ms per loop

len(df)=70k 中的时间安排

In [446]: %timeit df['col51'] = np.where(df['col1'] <3, df['col2'], np.where((df['col1'] <7) & (df['col1'] >=3 ), df['col3'], df['col4']))
100 loops, best of 3: 2.5 ms per loop

In [447]: %timeit df["col52"] = df.apply(lambda x: col52(x), axis=1)
1 loop, best of 3: 5.36 s per loop

In [448]: %timeit df["col53"] = [col53(c1,c2,c3,c4) for c1,c2,c3,c4 in zip(df.col1,df.col2,df.col3,df.col4)]
10 loops, best of 3: 96.3 ms per loop

计时代码:

#change 1000 to 10000 for 70k
df = pd.concat([df]*1000).reset_index(drop=True)

def col52(x):
    if x["col1"] < 3:
        return x["col2"]
    elif x["col1"] >=3 and x["col1"] < 7:
        return x["col3"]
    elif x["col1"] >= 7 and x["col1"] < 50:
        return x["col4"] 
def col53(c1,c2,c3,c4):
    if c1 < 3:
        return c2
    elif c1 >=3 and c1 < 7:
        return c3
    elif c1>= 7 and c1< 50:
        return c4    

df['col51'] = np.where(df['col1'] <3, df['col2'], np.where((df['col1'] <7) & (df['col1'] >=3 ), df['col3'], df['col4']))       
df["col52"] = df.apply(lambda x: col52(x), axis=1)
df["col53"] = [col53(c1,c2,c3,c4) for c1,c2,c3,c4 in zip(df.col1,df.col2,df.col3,df.col4)]
print (df)

【讨论】:

  • 太棒了!由于 pandas 索引数据帧,col52 是否比 col53 慢得多?列访问比行访问快得多吗?谢谢!
【解决方案2】:

一种方法是使用 pd.DataFrame.apply 函数:

    def col5(x):
        if x["col1"] < 3:
            return x["col2"]
        elif x["col1"] >=3 and x["col1"] < 7:
            return x["col3"]
        elif x["col1"] >= 7 and x["col1"] < 50:
            return x["col4"]              

此函数将数据帧的每一行作为输入。您可以按常规方式访问该行中的各种列值:x["col1"]、x["col2"] 等。

现在,使用 apply 函数在每一行或每一列上运行自定义函数(如上面的 col5)。参数 "axis" 为 1 用于将函数应用于每一行,为 0 用于将函数应用于每一列(在这种情况下,x 具有不同的结构,即它由您的索引而不是列名索引):

    df["col5"] = df.apply(lambda x: col5(x), axis=1)

此外,作为一般说明,apply 可能会非常慢,特别是当您有带有 if-else 块的函数时,因为对于每一行,您的处理器必须决定应该执行 if-else 块中的哪个语句(“流水线”和“分支预测”)。不过你应该没问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 2022-11-10
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多