J'ai un fichier CSV au format suivant
import numpy as np
import pandas as pd
import csv
df = pd.read_csv("testdata.csv")
with open("testdata.csv") as f:
reader = csv.reader(f, delimiter=",")
for i in reader:
print (i[0])
diffs=np.diff(i[0])
increased_value=np.median(diffs[diffs>0])
Pour la reproductibilité, j'ai inclus le fichier complet fichier CSV ici . À partir de la colonne 1, je voulais lire la ligne actuelle et la comparer avec la valeur de la ligne précédente. Si elle est supérieure, je voulais prendre la différence de la valeur actuelle par rapport à la précédente et stocker ( ajouter ) la différence dans une liste. Si la valeur actuelle est égale à la valeur de la ligne précédente, continuez la comparaison. Par exemple, dans l'exemple d'enregistrement ci-dessus que j'ai fourni, la troisième ligne ( 19 ) est supérieure à la valeur de la deuxième ligne ( 15 ) - donc ce sera ( 19-15 = 4 ), la quatrième ligne ( 52-19 = 33 ), etc.
Voici mon approche simple en utilisant numpy
86,1 15,2 19,3 52,4 15,5 13,6 18,7 20,8 49,9 266,10
Cependant, j'obtiens l'erreur IndexError: index d'assignation de liste hors limites . Comment puis-je corriger cette erreur afin de résoudre la tâche que j'ai mentionnée?
6 Réponses :
Je pense que c'est une meilleure façon
df = pd.read_csv("testdata.csv", header=None)
df
0 1
0 86 1
1 15 2
2 19 3
3 52 4
4 15 5
5 13 6
6 18 7
7 20 8
8 49 9
9 266 10
diffs = np.diff(df[0])
increased_value = np.median(diffs[diffs>0])
increased_value
17.0
C'est génial! Cependant, si vous imprimez diffs , cela donne array ([- 71, 4, 33, -37, -2, 5, 2, 29, 217]) . Comment pouvons-nous garder les nombres négatifs hors de la liste? Parce que je veux garder allumé UNIQUEMENT, la valeur actuelle est supérieure à la valeur de la ligne précédente.
diffs = diffs [diffs> 0] si vous souhaitez supprimer les valeurs négatives ou diffs [diffs <0] = 0 si vous souhaitez les remettre à zéro.
Et si je veux le faire dans le sens inverse? Cela signifie que lorsque la valeur de la ligne actuelle est inférieure à la valeur de la ligne précédente? Je l'ai fait comme ceci: np.median (diffs [diffs> 0]) mais les valeurs de la liste de tableaux que j'obtiens sont des nombres négatifs - [-71 - 37 -2] -37,0
diffs = np.diff (df [0]) * - 1 renvoie` [71, -4, -33, 37, 2, -5, -2, -29, -217] `< code> np.median (diffs [diffs> 0]) devrait retourner 37.0 Est-ce ce que vous espériez?
@AnanayMital, NON - la partie croissante comme vous l'avez fait dans votre réponse est correcte. Mais j'essayais de faire le contraire de la question que j'ai posée - que se passe-t-il si nous voulions le faire lorsque la valeur actuelle est plus petite que la valeur précédente? Pour cela (la partie inverse), je m'attendais à obtenir [-71 -37-2] et une valeur médiane de -37.0 .
ouais donc c'est juste np.median (diffs [diffs <0]) . Droite?
En gros, np.diff () attend une liste comme une entrée, et ce que vous passez est un entier. C'est la raison pour laquelle il échoue
Nous n'avons techniquement pas besoin de numpy
from statistics import median
from operator import itemgetter, lt, sub
first = itemgetter(0)
nums = []
with open('testdata.csv', 'r') as fin:
reader = csv.reader(fin)
for line in reader:
nums.append(int(first(line)))
res = [abs(sub(*t)) for t in zip(nums, nums[1:]) if lt(*t)]
[4, 33, 5, 2, 29, 217]
median(res)
17.0
Mais l'utilisation de numpy, comme le montre Ananay Mital, est dans 99% des cas préférable à l'utilisation de listes pour les données numériques.
cela dépend du cas d'utilisation mais dire que 99% des cas est une sur-portée, ces petites données sont triviales, nous pouvons être d'accord pour ne pas être d'accord
C'est super mais la ligne res = [abs (sub (* t)) pour t dans zip (nums, nums [1:]) si lt (* t)] dit Syntaxe invalide sur Python3
@aws_apprentice, d'où vient le 5 dans la liste [4, 33, 5, 2, 29, 217] ? Je suis confus. Si je le fais manuellement, j'obtiens 5 valeurs à la place.
@Brown, les exemples de données que vous avez fournis ont 13, puis 18, d'où le 5
La raison pour laquelle vous obtenez
IndexError: index d'affectation de liste hors de portée
est np. diff () prenant l'entrée comme un tableau ou une liste.
Comme
arr = []
df = pd.read_csv("testdata3.csv")
df
with open("testdata3.csv", mode='r', encoding='utf-8-sig') as f:
reader = csv.reader(f, delimiter=",")
for i in reader:
# print(i[0])
arr.append(int(i[0]))
diffs=abs(np.diff(arr))
increased_value=np.median(diffs[diffs>0])
Et si je veux le faire dans le sens inverse? Cela signifie que lorsque la valeur de la ligne actuelle est inférieure à la valeur de la ligne précédente? Je l'ai fait comme ceci: np.median (diffs [diffs> 0]) mais les valeurs de la liste de tableaux que j'obtiens sont des nombres négatifs - [-71 - 37 -2] -37,0
Utilisation de pandas s.diff ( ) :
data = StringIO("""86,1
15,2
19,3
52,4
15,5
13,6
18,7
20,8
49,9
266,10""")
df=pd.read_csv(data,header=None)
m1=df[0].diff().fillna(0)
#m1[m1>0].tolist()
#[4.0, 33.0, 5.0, 2.0, 29.0, 217.0]
m1[m1>0].median()
#17.0
Le problème que vous rencontrez est que lorsque vous essayez d'exécuter np.diff, le dtype par défaut de votre tableau est dtype U3, ce qui signifie que les valeurs de votre tableau ne sont pas des nombres, ce qui signifie qu'une conversion est nécessaire. Essayez ce qui suit:
with open("test_data.csv", "r") as f:
reader = csv.reader(f) ## no need for delimiter if your delimiter is ','
data = []
for row in reader:
data.append(row[0])
## ensure that you convert your data into numpy array with appropriate data type
## before carrying out any mathematical operations
np_array = np.array(data, dtype=np.uint8)
np_diff = np.diff(np_array)
np_median = abs(np.median(np_diff[np_diff > 0]))
print(np_median)
Si vous devez le faire régulièrement, vous pouvez toujours encapsuler une méthode. Essayez ceci.
Et si je veux le faire dans le sens inverse? Cela signifie que lorsque la valeur de la ligne actuelle est inférieure à la valeur de la ligne précédente? Je l'ai fait comme ceci: np.median (diffs [diffs> 0]) mais les valeurs de la liste de tableaux que j'obtiens sont des nombres négatifs - [-71 - 37 -2] -37,0
Vous attendez-vous à ce que votre résultat soit positif à tout moment?
Oui, je m'attends à ce que tous mes résultats soient positifs.
Je viens de faire une mise à jour pour inclure abs dans la variable np_median qui rendra tous les résultats positifs.
il imprime la liste entière array ([185, 4, 33, 219, 254, 5, 2, 29, 217], dtype = uint8) ce que je ne pense pas être juste. Pour la partie croissante, il ne doit imprimer que [4, 33, 5, 2, 29, 219] à la place. La question que j'ai posée dans mon premier commentaire à votre réponse doit également être imprimée [-71 -37-2]
Désolé pour la réponse tardive. J'ai juste essayé d'utiliser une liste ordinaire contenant vos nombres, c'est-à-dire data = [(86,1), (15,2), (19,3), (52,4), (15,5), (13,6), (18,7), (20,8), (49,9), (266,10)] puis en boucle pour obtenir la liste a = [86, 15, 19, 52, 15, 13, 18, 20 , 49, 266]. J'ai ensuite converti cela en tableau numpy puis appliquer diff pour obtenir un tableau ([185, 4, 33, 219, 254, 5, 2, 29, 217], dtype = uint8). À partir de là, j'ai utilisé abs (np.median (np_diff [np_diff> 0])) ce qui me donne 33,0. Pour que votre commentaire sur la valeur actuelle soit inférieure à la valeur précédente, vous devrez trier vos données, c'est-à-dire triées (données).
le diffs [diffs> 0] n'est qu'un filtre et ne vous indique pas réellement si la valeur de la ligne actuelle est inférieure à la valeur de la ligne précédente. Vous devrez faire une boucle pour cela.
y a-t-il des lignes vides dans votre fichier csv?
NON, il n'y a PAS de lignes vides dans le fichier CSV.