【问题标题】:How to create a new column to a pandas dataframe that was created after using apply()?如何为使用 apply() 后创建的 pandas 数据框创建一个新列?
【发布时间】:2017-04-16 10:39:50
【问题描述】:

读完一个excel文件后:

将熊猫导入为 pd

在:

df = pd.read_excel('file.xlsx')
df = df.drop('Unnamed: 0', 1)
df

输出:

    A   B   C   D   E
0   2345    typeA   NO  http://www.example.com/...
2   23423   483     NO  http://www.example.com/...
3   234234  typeC   NO  http://www.example.com/...
4   2343    typeA   NO  http://www.example.com/...
5   23423   typeA   NO  http://www.example.com/...
6   234     typeA   NO  http://www.example.com/...

我正在将几个函数应用于在使用 apply() 添加更多列之后创建的几个 pandas 数据框列:

在:

df['E'] = df['D'].apply(checker)
df

输出:

    A   B   C   D   E
0   2345    typeA   NO  http://www.example.com/...  OK
1   234     483     NO  http://www.example.com/...  FALSE
2   23423   483     NO  http://www.example.com/...  OK
3   234234  typeC   NO  http://www.example.com/...  OK
4   2343    typeA   NO  http://www.example.com/...  OK
5   23423   typeA   NO  http://www.example.com/...  FALSE
6   234     typeA   NO  http://www.example.com/...  OK

然后我做了:df = df[df.E == 'OK']df = df.loc[df.E =='OK']

然后,我正在对上述数据框应用一个新函数:

在:

df['F'] = df['D'].apply(new_function_foo)

虽然它实际上可以按我的意愿工作,但我收到了这个警告:

输出:

/usr/local/lib/python3.5/site-packages/ipykernel/__main__.py:10: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

我检查了文档,并尝试按照说明进行操作:

df['F'] = df.loc[['E']].apply(function_foo)

df['ColF'] = df.loc[:,'ColE'].apply(function_foo) 

但是,我不明白如何解决上述警告。那么,如何正确应用函数呢?

【问题讨论】:

  • 这不是警告的来源。在此之前,您可能在代码中的某处创建了 df 的副本。在该行之前查找类似 df2 = df 的内容或类似的内容
  • @StevenG,我忘了说:我做了df = df[df.E == 'OK']
  • 先这样做:df = df.loc[df.E =='OK']
  • 这是一个警告。如果你得到的结果正是你想要的,那没什么大不了的。是这样吗?
  • 你最好发个minimal reproducible example

标签: python python-3.x pandas numpy


【解决方案1】:

然后我做了:df = df[df.E == 'OK'] 和 df = df.loc[df.E =='OK']

这不是你想的那样。将df 重新分配给df 的切片或视图不会使其不是df 的切片或视图,它只是使您无法再引用原始df。不要这样做。

然后,当您尝试将该切片设置为某物时,pandas 会警告您将一个切片设置为另一个切片可能会导致意外结果(我认为这是因为 pandas 用于执行此操作的方法是基于您的口味python 实现,但我不是开发人员)。

无论如何,我认为您想要做的是(将来请始终显示预期的输出):

df.loc[df['E']=='OK','F'] = df[df['E']=='OK']['D'].apply(function_foo)

df.loc[df['E']=='OK','F'] = df.loc[df['E']=='OK','D'].apply(function_foo)

清除错误的重要部分是.loc 在等号之前。这告诉 pandas 将这些值放在完整数据框中的确切位置,因此不会感到困惑。您可能需要先使用df.insert(5,'F',None) 制作“F”列,以便有一些东西可以指向。

【讨论】:

    【解决方案2】:

    如果您可以复制数据框,您可以使用任何您喜欢的方法。例如,如果您这样做:

    df = df[df.E == 'OK'].copy()
    

    当你这样做时不会有错误:

    df['F'] = df['D'].apply(new_function_foo)
    

    【讨论】:

    • 这个帮助了我。使用.copy()有什么弊端?
    • 缺点是使用更多内存,因为过滤后的数据正在被复制到新的内存位置
    【解决方案3】:

    我仍然认为你做了一些你没有在你的代码中展示给我们的东西。试试这个:

    df = pd.DataFrame({'A': range(1, 10), 'B': range(1, 10), 'C': range(1, 10), 'D': range(1, 10), 'E': [1,1,1,2,2,2,2,3,4]})
    df = df.loc[df.E == 1]
    df['F'] = df.apply(sum, axis=1)
    In[71]: df
    Out[71]: 
       A  B  C  D  E   F
    0  1  1  1  1  1   5
    1  2  2  2  2  1   9
    2  3  3  3  3  1  13
    

    此代码不会产生警告。

    即使这样做:

    df = pd.DataFrame({'A': range(1, 10), 'B': range(1, 10), 'C': range(1, 10), 'D': range(1, 10), 'E': [1,1,1,2,2,2,2,3,4]})
    df = df[df.E == 1]
    df['F'] = df['D'].apply(lambda x: x/2)
    df
    Out[77]: 
       A  B  C  D  E  F
    0  1  1  1  1  1  0
    1  2  2  2  2  1  1
    2  3  3  3  3  1  1
    

    仍然没有产生警告。你能创建一个简短的、可复制的例子吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多