【问题标题】:How to iterate through a column in dataframe and update two new columns simultaneously?如何遍历数据框中的列并同时更新两个新列?
【发布时间】:2016-07-20 18:29:53
【问题描述】:

我知道我可以向数据框添加一列并将其值更新为从函数返回的值,如下所示:

df=pd.DataFrame({'x':[1,2,3,4]})

def square(x):
    return x*x

df['x_squared'] = [square(i) for i in df['x']]

但是,我面临一个问题,即实际函数返回两个项目,我想将这两个项目放在两个不同的新列中。我在这里写了一个伪代码来更清楚地描述我的问题:

df=pd.DataFrame({'x':[1,2,3,4]})

def squareAndCube(x):
    return x*x, x*x*x

#below is a pseudo-code
df['x_squared'], df['x_cubed'] = [squareAndCube(i) for i in df['x']]

上面的代码给了我一条错误消息,说“要解压的值太多”。 那么,我应该如何解决这个问题?

【问题讨论】:

    标签: python numpy pandas dataframe multiple-columns


    【解决方案1】:

    你可以用矢量化的方式来做,像这样 -

    df['x_squared'], df['x_cubed'] = df.x**2,df.x**3
    

    或者使用那个自定义函数,像这样 -

    df['x_squared'], df['x_cubed'] = squareAndCube(df.x)
    

    回到你的循环案例,在作业的右侧,你有:

    In [101]: [squareAndCube(i) for i in df['x']]
    Out[101]: [(1, 1), (4, 8), (9, 27), (16, 64)]
    

    现在,在左侧,你有df['x_squared'], df['x_cubed'] =。因此,它期望所有行的平方数作为第一个输入分配。从上面显示的列表中,第一个元素不是那个,它实际上是第一行的正方形和立方体。因此,解决方法是“转置”该列表并分配为新列。因此,修复将是 -

    In [102]: L = [squareAndCube(i) for i in df['x']]
    
    In [103]: map(list, zip(*L))  # Transposed list
    Out[103]: [[1, 4, 9, 16], [1, 8, 27, 64]]
    
    In [104]: df['x_squared'], df['x_cubed'] = map(list, zip(*L))
    

    为了NumPy broadcasting的爱!

    df['x_squared'], df['x_cubed'] = (df.x.values[:,None]**[2,3]).T
    

    【讨论】:

    • 很好的答案@Divakar,+1
    • 顺便说一句,广播比我的 log_dot 解决方案快 WAY1!!1。
    • 这是一个非常好的答案!我用这个squareAndCube() 函数来解决我的问题。我真正的问题是我需要使用地址作为输入并返回纬度和经度。所以最后我选择了mapzip 方法。但是很高兴知道还有其他几种方法!谢谢@Divakar。
    【解决方案2】:

    这适用于正数。思考如何概括,但这个解决方案的简洁让我分心。

    df = pd.DataFrame(range(1, 10))
    a = np.arange(1, 4).reshape(1, -1)
    
    np.exp(np.log(df).dot(a))
    

    【讨论】:

    • 受此启发,添加了另一种使用广播的方法! :)
    • @Divakar 我知道你会的 :-) 我正要向你寻求帮助,但因为别的事情而分心了。
    【解决方案3】:

    像这样使用df.loc怎么样:

    df=pd.DataFrame({'x':[1,2,3,4]})
    
    def square(x):
        return x*x
    
    df['x_squared'] = df['x_cubed'] = None
    df.loc[:, ['x_squared', 'x_cubed']] = [squareAndCube(i) for i in df['x']]
    

    给予

       x  x_squared  x_cubed
    0  1          1        1
    1  2          4        8
    2  3          9       27
    3  4         16       64
    

    非常 接近您所拥有的,但列需要存在,df.loc 才能工作。

    对于初学者,df.loc 有两个参数,一个是您要处理的行列表 - 在本例中为 :,表示所有行,以及一个列列表 - ['x_squared', 'x_cubed']

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-03
      • 2019-12-16
      • 1970-01-01
      • 2022-07-07
      • 2018-04-01
      • 1970-01-01
      相关资源
      最近更新 更多