Changer les valeurs dans les pandas DataFrame

j'ai un problème à changer les valeurs d'une base de données. Je veux également consulter au sujet d'un problème que je dois résoudre et la bonne façon d'utiliser les pandas pour le résoudre. Je vais apprécier aide sur les deux. J'ai un fichier contenant des informations sur le degré de correspondance des fichiers audio avec les haut-parleurs. Le fichier ressemble à quelque chose comme ça:

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

ce que je dois faire, c'est une sorte de comptage sophistiqué. J'ai besoin de grouper les résultats par orateur, et de calculer pour chaque orateur un certain calcul. Je passe ensuite à l'orateur qui a fait le meilleur calcul pour moi, mais avant de procéder je dois marquer tous les fichiers que j'ai utilisés pour le calcul comme étant utilisés, c.-à-d. changer la valeur isUsed pour chaque ligne dans laquelle ils apparaissent (les fichiers peuvent apparaître plus d'une fois) à TRUE. Puis je fais une autre itération. Calculer pour chaque haut-parleur, marquer les fichiers utilisés et ainsi de suite jusqu'à ce qu'il ne reste plus de haut-parleurs à calculer.

j'ai beaucoup réfléchi à la façon de mettre en œuvre ce processus en utilisant pandas (c'est assez facile à implémenter en python régulier mais cela va prendre beaucoup de bouclage et de structuration de données qui, à mon avis, va ralentir le processus de manière significative, et aussi j'utilise ce processus pour apprendre plus profondément les capacités des pandas)

je suis venu avec la solution suivante. Comme préparation, je vais Grouper par nom de haut-parleur et définir le nom du fichier comme index par la méthode set_index. Je vais ensuite itérer sur le groupbyObj et appliquer la fonction de calcul, qui retournera le haut-parleur sélectionné et les fichiers à être marqué comme utilisé.

puis je vais itérer les fichiers et les marquer comme utilisés (ce serait rapide et simple puisque je les ai mis en index à l'avance), et ainsi de suite jusqu'à ce que je finisse de calculer.

tout d'abord, je ne suis pas sûr de cette solution, alors n'hésitez pas à me dire ce que vous en pensez. Maintenant, j'ai essayé d'implémenter ceci, et j'ai eu des problèmes:

j'ai d'Abord indexé par le nom de fichier, pas de problème ici:

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

Alors I choisissez un fichier et vérifié que je reçois les entrées pertinentes à ce fichier:

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

maintenant des problèmes ici aussi. Puis j'ai essayé de changer la valeur isUsed pour ce fichier en True, et là où j'ai eu le problème:

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

Donc, vous voyez le problème. Rien n'a changé. Ce que je fais mal? Le problème décrit ci-dessus devrait-il être résolu en utilisant pandas?

Et aussi: 1. Comment puis-je approcher un groupe spécifique par un objet groupby? bcz j'ai pensé que peut-être au lieu de définir les dossiers comme indexés, groupant par un dossier, et l'utilisation de ce groupby obj pour appliquer une fonction changeante à tous ses événements. Mais je n'ai pas trouvé un moyen d'approcher un groupe spécifique et de passer le nom du groupe comme paramètre et appel s'appliquent sur tous les groupes et puis agir seulement sur l'un d'eux ne me semble pas "juste".

j'espère que c'est pas pour longtemps... :)

9
demandé sur idoda 2013-08-01 17:24:04

1 réponses

indexation les objets Panda peuvent retourner deux objets fondamentalement différents: une vue ou une copie.

Si mask est une tranche de base, puis df.ix[mask] retourne un viewdf. Les vues partagent les mêmes données sous-jacentes que l'objet original (df). Donc modifier la vue, modifie aussi l'objet original.

Si mask est quelque chose de plus compliqué, comme une séquence arbitraire d'indices, puis df.ix[mask] retourne un copier de certains lignes df. Modifier la copie n'a aucun effet sur l'original.

Dans votre cas, puisque les lignes qui partagent le même wave_path se produisent à des endroits arbitraires,ind_res.ix[example_file] renvoie une copie. Donc

ind_res.ix[example_file]['isUsed'] = True

n'a aucun effet sur ind_res.

a la place, vous pouvez utiliser

ind_res.ix[example_file, 'isUsed'] = True

modifier ind_res. Cependant, voir ci-dessous pour un groupby suggestion qui je pense pourrait être plus proche de ce que vous voulez vraiment.

Jeff a déjà à condition a lien vers les Pandas docs état

Les règles sur le moment où une vue sur les données retournées sont entièrement ça dépend de NumPy.

Voici le (compliqué) règles qui décrivent lorsqu'une vue ou une copie est renvoyée. Fondamentalement, cependant, la règle est si l'index demande une tranche régulièrement espacée du tableau sous-jacent puis une vue est retournée, sinon une copie (par nécessité) est retourner.


voici un exemple simple qui utilise la tranche de base. Une vue est retournée par df.ix, et modifier subdf modifie df ainsi:

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

voici un exemple simple qui utilise "l'indexation de fantaisie" (lignes arbitraires sélectionnées). Une copie est renvoyée par df.ix. C'est pourquoi modifier subdf n'affecte pas 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

Avis la seule différence entre les deux exemples est que dans le premier, où un la vue est retourné, l'indice a été [0,1,2,3], tandis que dans le second, dont une copie est retourné, l'indice a été [0,1,0,3].

puisque nous sommes des lignes sélectionnées où l'index est 0, dans le premier exemple, nous pouvons le faire avec une tranche de base. Dans le deuxième exemple, les lignes où index égale 0 peuvent apparaître à des endroits arbitraires, donc une copie doit être retournée.


en dépit d'avoir crié sur la subtilité des Pandas / découpage de pépins, Je ne pense vraiment pas que

ind_res.ix[example_file, 'isUsed'] = True

est ce que vous cherchez en fin de compte. Vous voulez probablement faire quelque chose de plus comme

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)

ce qui donne

   A   B     C
0  0   1  True
1  1   4  True
2  0   7  True
3  1  10  True
17
répondu unutbu 2013-08-14 10:08:17