Pandas 更改dataframe中的值无效

Pandas 更改dataframe中的值无效,pandas,dataframe,Pandas,Dataframe,我在更改数据帧中的值时遇到问题。我还想就我需要解决的一个问题以及如何使用熊猫来解决这个问题进行咨询。这两方面我都很感激。 我有一个文件,其中包含有关音频文件与扬声器匹配程度的信息。该文件类似于: wave_path spk_name spk_example# score mark comments isUsed 190 122_65_02.04.51.800.wav idoD idoD 88 NaN NaN False 19

我在更改数据帧中的值时遇到问题。我还想就我需要解决的一个问题以及如何使用熊猫来解决这个问题进行咨询。这两方面我都很感激。 我有一个文件,其中包含有关音频文件与扬声器匹配程度的信息。该文件类似于:

wave_path   spk_name    spk_example#    score   mark    comments    isUsed
190  122_65_02.04.51.800.wav     idoD    idoD    88  NaN     NaN     False
191  121_110_20.17.27.400.wav    idoD    idoD    87  NaN     NaN     False
192  121_111_00.34.57.300.wav    idoD    idoD    87  NaN     NaN     False
193  103_31_18.59.12.800.wav     idoD    idoD_0  99  HIT     VP  False
194  131_101_02.08.06.500.wav    idoD    idoD_0  96  HIT     VP  False
我需要做的是一种复杂的计数。我需要按演讲者对结果进行分组,并为每个演讲者计算一些计算。然后,我继续使用为我进行最佳计算的扬声器,但在继续之前,我需要将用于计算的所有文件标记为正在使用,即将它们出现的每一行的isUsed值(文件可能出现多次)更改为TRUE。然后我进行另一次迭代。为每个扬声器计算,标记使用过的文件,依此类推,直到没有更多的扬声器需要计算

关于如何使用pandas实现该过程,我考虑了很多(在常规python中实现很容易,但需要大量的循环和数据结构,我猜这将大大降低该过程的速度,而且我正在使用该过程更深入地学习pandas的能力)

我提出了以下解决方案。作为准备步骤,我将按说话人名称分组,并通过set_index方法将文件名设置为索引。然后,我将迭代groupbyObj并应用计算函数,该函数将返回选定的扬声器和要标记为已使用的文件

然后我将迭代这些文件,并将它们标记为已使用(这将是快速而简单的,因为我预先将它们设置为索引),依此类推,直到我完成计算

首先,我不确定这个解决方案,所以请随时告诉我您的想法。 现在,我试着实现了这一点,但遇到了麻烦:

首先,我按文件名编制索引,这里没有问题:

In [53]:

    marked_results['isUsed'] = False
    ind_res = marked_results.set_index('wave_path')
    ind_res.head()

Out[53]:
    spk_name    spk_example#    score   mark    comments    isUsed
    wave_path                       
    103_31_18.59.12.800.wav      idoD    idoD    99  HIT     VP  False
    131_101_02.08.06.500.wav     idoD    idoD    99  HIT     VP  False
    144_35_22.46.38.700.wav      idoD    idoD    96  HIT     VP  False
    41_09_17.10.11.700.wav       idoD    idoD    93  HIT     TEST    False
    122_188_03.19.20.400.wav     idoD    idoD    93  NaN     NaN     False
然后我选择一个文件并检查是否获得了与该文件相关的条目:

In [54]:

    example_file = ind_res.index[0];
    ind_res.ix[example_file]

Out[54]:
    spk_name    spk_example#    score   mark    comments    isUsed
    wave_path                       
    103_31_18.59.12.800.wav  idoD    idoD    99  HIT     VP  False
    103_31_18.59.12.800.wav  idoD    idoD_0  99  HIT     VP  False
    103_31_18.59.12.800.wav  idoD    idoD_1  97  HIT     VP  False
    103_31_18.59.12.800.wav  idoD    idoD_2  95  HIT     VP  False
现在问题也来了。然后我尝试将该文件的isUsed值更改为True,这就是我遇到问题的原因:

In [56]:

    ind_res.ix[example_file]['isUsed'] = True
    ind_res.ix[example_file].isUsed = True
    ind_res.ix[example_file]
Out[56]:
    spk_name    spk_example#    score   mark    comments    isUsed
    wave_path                       
    103_31_18.59.12.800.wav  idoD    idoD    99  HIT     VP  False
    103_31_18.59.12.800.wav  idoD    idoD_0  99  HIT     VP  False
    103_31_18.59.12.800.wav  idoD    idoD_1  97  HIT     VP  False
    103_31_18.59.12.800.wav  idoD    idoD_2  95  HIT     VP  False
所以,你看到问题了。一切都没有改变。我做错了什么?上述问题是否应使用熊猫解决

而且: 1.如何通过groupby对象接近特定组?bcz我想也许不是将文件设置为索引、按文件分组,而是使用groupby obj将一个变化的函数应用于它的所有引用。但是我没有找到一种方法来接近一个特定的组,并将组名作为参数传递给所有组,然后对所有组调用apply,然后只对其中一个组执行操作,这对我来说似乎不“正确”


我希望不会太久……:)

索引熊猫对象可以返回两个根本不同的对象:视图或副本

如果
mask
是基本切片,则
df.ix[mask]
返回
df
的视图。视图与原始对象共享相同的基础数据(
df
)。因此,修改视图也会修改原始对象

如果
mask
更复杂,例如索引的任意序列,则
df.ix[mask]
返回
df
中某些行的副本。修改副本对原件没有影响

在您的情况下,由于共享相同
wave\u路径的行出现在任意位置,
ind\u res.ix[示例文件]
返回一个副本。所以

ind_res.ix[example_file]['isUsed'] = True
ind\u res
没有影响

相反,你可以使用

ind_res.ix[example_file, 'isUsed'] = True
要修改
ind\u res
。不过,请参见下面的
groupby
建议,我认为这可能更接近您真正想要的

Jeff已经提供了一份报告,说明

关于何时返回数据视图的规则完全相同 依赖NumPy

这是最复杂的。但是,基本上,规则是,如果索引请求底层数组的规则间隔切片,则返回一个视图,否则返回一个副本(出于必要)


下面是一个使用基本切片的简单示例。视图由
df.ix
返回,因此修改
subdf
也会修改
df

import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(12).reshape(4,3), 
         columns=list('ABC'), index=[0,1,2,3])

subdf = df.ix[0]
print(subdf.values)
# [0 1 2]
subdf.values[0] = 100
print(subdf)
# A    100
# B      1
# C      2
# Name: 0, dtype: int32

print(df)           # df is modified
#      A   B   C
# 0  100   1   2
# 1    3   4   5
# 2    6   7   8
# 3    9  10  11

下面是一个简单的示例,它使用“奇特的索引”(选择任意行)。通过
df.ix
返回副本。因此修改
subdf
不会影响
df

df = pd.DataFrame(np.arange(12).reshape(4,3), 
         columns=list('ABC'), index=[0,1,0,3])

subdf = df.ix[0]
print(subdf.values)
# [[0 1 2]
#  [6 7 8]]

subdf.values[0] = 100
print(subdf)
#      A    B    C
# 0  100  100  100
# 0    6    7    8

print(df)          # df is NOT modified
#    A   B   C
# 0  0   1   2
# 1  3   4   5
# 0  6   7   8
# 3  9  10  11
请注意,这两个示例之间的唯一区别在于,在第一个示例中,返回视图的索引是[0,1,2,3],而在第二个示例中,返回副本的索引是[0,1,0,3]

由于我们选择了索引为0的行,因此在第一个示例中,我们可以使用基本切片来实现这一点。在第二个示例中,索引等于0的行可能出现在任意位置,因此必须返回副本


尽管我一直在大肆宣扬熊猫/裸体切片的微妙之处,但我真的不这么认为

ind_res.ix[example_file, 'isUsed'] = True
这就是你最终想要的。你可能想做一些更像

import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(12).reshape(4,3), 
                  columns=list('ABC'))
df['A'] = df['A']%2
print(df)
#    A   B   C
# 0  0   1   2
# 1  1   4   5
# 2  0   7   8
# 3  1  10  11

def calculation(grp):
    grp['C'] = True
    return grp

newdf = df.groupby('A').apply(calculation)
print(newdf)
产生

   A   B     C
0  0   1  True
1  1   4  True
2  0   7  True
3  1  10  True

您正在修改一个副本,
.ix[示例文件,'isUsed']
请参见此处:感谢您的解释。我觉得很烦人,因为我不能事先知道我是要看一份还是要复印一份。这个设计不合我的口味。关于你的最后一个建议,问题是一些文件在多个组中出现。因此,我需要找到所有组中的所有外观并对其进行修改。相反,我选择提前按文件编制索引,并一次性更改所有apearnces。如果你仍然认为有更好的方法,我很乐意听你说。你能告诉我,我能从groupby对象中通过名称访问一个组吗?非常感谢!使用groupby的建议无效。“calculation”函数内部的“isUsed”列已更改,但外部的数据帧未更改。你知道为什么吗?会是那样吗