Python 在函数内追加数据帧

Python 在函数内追加数据帧,python,pandas,function,dataframe,Python,Pandas,Function,Dataframe,我有一个函数test,它获取一个数据帧并向其添加数据。我想更改放入函数中的全局变量。我的脚本如下: import pandas as pd global dff def test(df): df = df.append({'asdf':1, 'sdf':2}, ignore_index=True) return(df) dff = pd.DataFrame() test(dff) 在此之后,dff保持为空;它没有被编辑。但是,如果您这样做: import pandas as

我有一个函数
test
,它获取一个数据帧并向其添加数据。我想更改放入函数中的全局变量。我的脚本如下:

import pandas as pd
global dff

def test(df):
    df = df.append({'asdf':1, 'sdf':2}, ignore_index=True)
    return(df)

dff = pd.DataFrame()
test(dff)
在此之后,
dff
保持为空;它没有被编辑。但是,如果您这样做:

import pandas as pd

def test(df):
    df['asdf'] = [1,2,3]
    return(df)

dff = pd.DataFrame()
test(dff)
dff
将在
'asfd'列下有
[1,2,3]
。请注意,我甚至不必将变量声明为
global

为什么会这样

我真的很想知道,因为第二次我认为我理解了可变工作空间,我被证明是错的,我对经常遇到这种情况感到厌倦*

我知道解决问题的办法是:

import pandas as pd

def test(df):
    df = df.append({'asdf':1, 'sdf':2}, ignore_index=True)
    return(df)

dff = pd.DataFrame()
dff = test(dff)
但我真的只是想弄明白为什么初始方法不起作用,特别是考虑到我展示的第二个脚本

*很明显,它不是完全的BS,但经过3年的随意编程后,我无法理解它

  • 我认为数据帧、列表和字典所有这些数据类型都是通过引用传递给函数的,因此这种行为也是如此
  • 在您要追加的第一个脚本中,它作为
    append
    返回一个新对象被追加到一个全新的对象,因此它没有填充原始数据帧
  • 在第二个脚本中,您将一个特定的dataframe列指定给原始dataframe对象,因此它用列填充原始dataframe对象,因为您正在修改原始对象
  • 您可以查看以下答案:
  • 选中此列表示例:

    def test1(a):
        a.append(1)
    
    def test2(a):
        a = [1, 2, 3]
    
    def test3(a):
        a[0] = 10
    
    aa = list()
    test1(aa)
    print(aa)
    
    aa = list()
    test2(aa)
    print(aa)
    
    aa = list([1])
    test3(aa)
    print(aa)
    
  • 输出:

    [1]
    []
    [10]
    
  • 将上述列表示例与熊猫数据帧示例关联起来
  • 如果您检查Dataframe的
    追加
    功能:
    DataFrame.append(其他,忽略索引=False,验证完整性=False,排序=None)[source]
    将其他行追加到此帧的末尾,返回一个新对象。不在此框架中的列将作为新列添加。
  • 正如您在描述中所看到的,
    append
    返回一个新对象
  • 您使用
    global
    关键字的方式是错误的。。。我认为,即使在第一个脚本中没有
    global
    ,也不会有任何区别。。。我不知道有关
    global
    关键字的详细信息,因此我不会提及任何有关它的内容。。但我知道如何使用关键字,这绝对不是正确的使用方法
更新: 我在PyCon 2015上找到了一篇非常好的演讲,它解释了我试图在下面解释的内容,但通过图表可以让它更加清晰。我将留下下面的解释来解释最初的3个脚本是如何工作的,但我建议去看视频:


所以,我想我已经弄清楚了上面两个脚本中发生了什么。我要试着把它拆开。如果需要,请随时纠正我

一些规则:

  • 变量是指向实际保存数据的基础对象的链接/指针的名称。例如,街道地址。街道地址不是房子;它只是指向一所房子。因此,地址(101 Streetway Rd.)就是指针。在GPS中,您可能会将其标记为“家”。“Home”一词就是变量本身

  • 函数处理对象,而不是变量或指针。将变量传递给函数时,实际上传递的是对象,而不是变量或指针。继续房屋示例,如果要向房屋添加甲板,则希望甲板承包商处理房屋,而不是元物理地址

  • 函数中的
    return
    命令返回指向对象的指针。因此,这将是房子的地址,而不是房子或你可能称之为房子的名字

  • =
    是一个函数,表示“指向此对象”。
    =
    前面的变量是输出,右边的变量是输入。这就是给房子命名的行为。所以
    Home=101 Streetway-Rd.
    使变量
    Home
    指向101 Streetway-Rd上的房子。假设您搬进了邻居的房子,即102 Streetway-Rd。这可以通过
    Home=Neighbor's house
    完成。现在,
    Home
    现在是指针102 Streetway Rd的名称

  • 在这里,我将使用
    -->
    来表示“指向”

    在我们开始脚本之前,让我们从我们想要的开始。我们需要变量指向的对象
    objdf

    脚本1: (没有
    全局dff
    ,因为它不做任何相关的事情)

    让我们来看看这个函数。在我们到达以下位置之前,不会发生任何有趣的事情:

    dff=pd.DataFrame()

    这里,我们将变量
    dff
    分配给由
    pd.DataFrame
    创建的对象,它是一个空数据帧。我们将此对象称为
    objdf
    。因此,在这一行的末尾,我们有
    dff-->objdff

    下一行:
    test(dff)

    函数在对象上工作,所以我们要在
    dff
    指向的对象上运行函数
    test
    ,即
    objdf
    。这就引出了函数本身

    def测试(df):

    这里,我们有一个本质上是
    =
    函数。传递到测试函数
    objdf
    的对象由函数变量
    df
    指向。所以现在
    df--->objdf
    dff--->objdf

    转到下一行:
    df=df.append(…)

    让我们从
    df.append(…)
    开始。
    .append(…)
    被传递到
    objdf
    上。这使得对象
    objdf
    运行一个名为“append”的函数。正如@Jai所指出的,
    .append(…)
    方法使用
    return
    命令输出一个全新的数据帧,该数据帧中附加了数据。我们会打电话给
    import pandas as pd
    
    def test(df):
        df = df.append({'asdf':1, 'sdf':2}, ignore_index=True)
        return(df)
    
    dff = pd.DataFrame()
    test(dff)
    
    import pandas as pd
    
    def test(df):
        df['asdf'] = [1,2,3]
        return(df)
    
    dff = pd.DataFrame()
    test(dff)
    
    import pandas as pd
    
    def test(df):
        df = df.append({'asdf':1, 'sdf':2}, ignore_index=True)
        return(df)
    
    dff = pd.DataFrame()
    dff = test(dff)