循环遍历熊猫数据框字典并进行修改的最佳实践是什么?

Boo*_*oom 5 python pandas

我有一个 DataFrames 字典,其中的键是指数据的年份。我想遍历字典并对数据帧进行修改。我对 dfs 的列名和内容进行了修改。

for year, df in df_data.items():
    cols = df .columns
    new_cols = [re.sub(r'\s\d{4}\-\d{2}', '', c) for c in cols]
    df.columns = new_cols

for year, df in df_data.items():
    df['Date'] = pd.to_datetime(df['Date'], infer_datetime_format=True)
    df = df.drop_duplicates(subset='Id', keep='first')
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释这样做的行为吗?特别是 dfs 如何存储在内存中以及为什么列的重命名有效但对内容的修改无效。另外,有没有最好的方法来做到这一点,要么复制 df,然后在 dict 索引中替换它,要么不断更改 df_data[year] 引用?

Dav*_*ave 1

正如 @juanpa.arrivillaga 上面所描述的,drop_duplicates 返回一个 dataframe,您将其分配给局部变量df。考虑以下示例:

a = [0, 1]
for b in a:
    print(f'b: {b}')
    b = 2
    print(f'b: {b}') 

print(f'a: {a}')
Run Code Online (Sandbox Code Playgroud)

这是输出:

b: 0
b: 2
b: 1
b: 2
a: [0, 1]
Run Code Online (Sandbox Code Playgroud)

您可以看到局部变量b被赋值为 value ,但循环完成后2列表没有变化。a这是因为b是对列表的引用,而不是列表本身。分配b = 2会导致b更改为对整数的引用2,但不会导致引用的列表项b更改为对整数的引用2。在第一个循环开始时,引用如下所示:

b -> a[0] -> the integer 0
Run Code Online (Sandbox Code Playgroud)

分配b = 2结果如下:

a[0] -> the integer 0
   b -> the integer 2
Run Code Online (Sandbox Code Playgroud)

不是这个:

b -> a[0] -> the integer 2
Run Code Online (Sandbox Code Playgroud)

要在循环中改变对象,您必须仅使用就地工作的方法,或者必须使用对该对象的直接引用:

for year in df_data.keys():
    cols = df[year].columns
    new_cols = [re.sub(r'\s\d{4}\-\d{2}', '', c) for c in cols]
    df[year].columns = new_cols

for year in df_data.keys():
    df[year]['Date'] = pd.to_datetime(df[year]['Date'], infer_datetime_format=True)
    df[year] = df[year].drop_duplicates(subset='Id', keep='first')
Run Code Online (Sandbox Code Playgroud)