熊猫“试图在数据帧的切片副本上设置一个值”

Posted

技术标签:

【中文标题】熊猫“试图在数据帧的切片副本上设置一个值”【英文标题】:Pandas "A value is trying to be set on a copy of a slice from a DataFrame" 【发布时间】:2021-10-13 10:49:13 【问题描述】:

理解文档有点困难

请参阅文档中的注意事项:https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy dfbreed['x'] = dfbreed.apply(testbreed, axis=1) C:/Users/erasmuss/PycharmProjects/Sarah/farmdata.py:38: SettingWithCopyWarning: 试图在 DataFrame 中的切片副本上设置一个值。 尝试改用 .loc[row_indexer,col_indexer] = value

代码基本上是重新排列和清理一些数据,使分析更容易。 每个动物在给定的行中编码,但有重复、空白和一些其他稀疏值 想法是基本上将行堆叠成列并获取每只动物的有用数据(按日​​期和最终 BCS 的体重)

Initial DF 数据帧的几个sn-ps

Output Format 输出DF/csv

import pandas as pd
import numpy as np

#Function for cleaning up multiple entries of breeds
def testbreed(x):
    if x.first_valid_index() is None:
        return None
    else:
        return x[x.first_valid_index()]

#Read Data
df1 = pd.read_csv("farmdata.csv")

#Drop empty rows
df1.dropna(how='all', axis=1, inplace=True)

#Copy to extract Weights in DF2
df2 = df1.copy()
df2 = df2.drop(['BCS', 'Breed','Age'], axis=1)

#Pivot for ID names in DF1
df1 = df1.pivot(index='ID', columns='Date', values=['Breed','Weight', 'BCS'])

#Pivot for weights in DF2
df2 = df2.pivot(index='ID', columns='Date', values = 'Weight')

#Split out Breeds and BCS into individual dataframes w/Duplicate/missing data for each ID
df3 = df1.copy()
dfbreed = df3[['Breed']]
dfBCS = df3[['BCS']]

#Drop empty BCS columns
df1.dropna(how='all', axis=1, inplace=True)

#Shorten Breed and BCS to single Column by grabbing first value that is real. see function above
dfbreed['x'] = dfbreed.apply(testbreed, axis=1)
dfBCS['x'] = dfBCS.apply(testbreed, axis=1)

#Populate BCS and Breed into new DF
df5= pd.DataFrame(data=None)
df5['Breed'] = dfbreed['x']
df5['BCS'] = dfBCS['x']

#Join Weights
df5 = df5.join(df2)

#Write output
df5.to_csv(r'.\out1.csv')

我想采用 BCS 和 Breed 数据帧,这些数据帧由 Breed 或 BCS 在列上进行多索引,然后按日期获取日期行中的第一个非 NaN 值并将其设置为名为品种的列。

让列在 DF 上原位选择第一个唯一值时遇到了很多麻烦 我找到了一个 2015 年答案的解决方法:

2015 Answer

它在顶部定义了函数。 直观地阅读在切片副本上设置值是有意义的, 但我似乎想不出一种方法让它作为直接替换或基于索引的方式工作。

我应该循环遍历吗?

从The second answer here尝试 我明白了

dfbreed.loc[:,'Breed'] = dfbreed['Breed'].apply(testbreed, axis=1)
dfBCS.loc[:, 'BCS'] = dfBCS.apply['BCS'](testbreed, axis=1)

返回

ValueError:使用可迭代设置时必须具有相等的 len 键和值

我认为这与多索引有关 键出现为:

MultiIndex([('品种', '1/28/2021'), (“品种”,“2021 年 2 月 12 日”), (“品种”,“2021 年 2 月 4 日”), (“品种”,“2021 年 3 月 18 日”), (“品种”,“2021 年 7 月 30 日”)], 名称=[无,'日期']) MultiIndex([('BCS', '1/28/2021'), ('BCS','2/12/2021'), (“BCS”,“2021 年 2 月 4 日”), (“BCS”,“2021 年 3 月 18 日”), ('BCS', '7/30/2021')], 名称=[无,'日期'])

抱歉,问题太长了? 谁能帮帮我?

谢谢。

【问题讨论】:

【参考方案1】:

您将 dfbreed 创建为:

dfbreed = df3[['Breed']]

所以它是原始 DataFrame 的视图(仅限于这一列)。

请记住,视图没有任何自己的数据缓冲区,它只是“查看”的工具 原始 DataFrame 的片段,具有只读访问权限。

当您尝试执行dfbreed['x'] = dfbreed.apply(...) 时,您 实际上试图违反只读访问模式。

为避免此错误,请将 dfbreed 创建为“独立”DataFrame:

dfbreed = df3[['Breed']].copy()

现在 dfbreed 拥有自己的数据缓冲区,您可以随意更改数据。

【讨论】:

谢谢。这是有道理的,而且非常简单。谢谢你的课!

以上是关于熊猫“试图在数据帧的切片副本上设置一个值”的主要内容,如果未能解决你的问题,请参考以下文章

来自熊猫数据框嵌套字典的熊猫数据框

熊猫迭代更新列值

基于索引从大熊猫系列列表中提取到另一个大熊猫系列

熊猫应用函数将多个值返回到熊猫数据框中的行

熊猫:问题数据添加到数据帧大熊猫

什么是“熊猫烧香”啊