如何从Python中的文本文件计算中位数?

时间:2018-12-26 13:39:24

标签: python

我有这个文本文件:

Category;currency;sellerRating;Duration;endDay;ClosePrice;OpenPrice;Competitive?
Music/Movie/Game;US;3249;5;Mon;0,01;0,01;No

Music/Movie/Game;US;3249;5;Mon;0,01;0,01;No

Music/Movie/Game;US;3249;5;Mon;0,01;0,01;No

Music/Movie/Game;US;3249;5;Mon;0,01;0,01;No

Music/Movie/Game;US;3249;5;Mon;0,01;0,01;No

Music/Movie/Game;US;3249;5;Mon;0,01;0,01;No

Music/Movie/Game;US;3249;5;Mon;0,01;0,01;No

Automotive;US;3115;7;Tue;0,01;0,01;No

Automotive;US;3115;7;Tue;0,01;0,01;No

Automotive;US;3115;7;Tue;0,01;0,01;Yes

实际文件中没有任何空白,否则将显示错误。我想计算每个类别的中位数。因此,例如,我想从sellerRating计算中位数。到目前为止,我已经有了(因为我还需要计算平均值,但是我设法做到了):

import csv
import locale
import statistics
from pprint import pprint, pformat

import locale

locale.setlocale(locale.LC_ALL, 'Dutch_Netherlands.1252')

avg_names = 'sellerRating', 'Duration', 'ClosePrice', 'OpenPrice'
averages = {avg_name: 0 for avg_name in avg_names}


num_values = 0
 with open('bijlage.txt', newline='') as bestand:
     csvreader = csv.DictReader(bestand, delimiter=';')
     for row in csvreader:
        num_values += 1
        for avg_name in avg_names:
             averages[avg_name] += locale.atof(row[avg_name])


for avg_name, total in averages.items():
averages[avg_name] = total / num_values

print('raw results:')
pprint(averages)

print() 
print('Averages:')
for avg_name in avg_names:
    rounded = locale.format_string('%.2f', round(averages[avg_name], 2),
                               grouping=True)
    print('  {:<13} {:>10}'.format(avg_name, rounded))

我试图这样做:     进口统计     打印(statistics.median(平均值) 但这不起作用。 谁能帮我,因为我不知道从这里去哪里? 提前非常感谢!

3 个答案:

答案 0 :(得分:3)

要扩展Guarav的建议,请使用熊猫:

import pandas as pd
import locale

avg_names = 'sellerRating', 'Duration', 'ClosePrice', 'OpenPrice'
frame = pd.read_csv(open('bijlage.txt'), delimiter=';')
# now you can access columns like a dictionary
frame['sellerRating'].median() # this will give you the median of the entire column

avg = [frame[i].apply(locale.atof).median() if frame[i].dtype == object else frame[i].median() for i in avg_names]
print(avg)

解释理解中发生了什么:
我们逐列进行,如果需要,将逗号分隔的浮点数转换为点分隔的浮点数(apply函数),然后获得整个列的中位数

答案 1 :(得分:2)

使用pandas库进行操作,因为所有代码都将减少为几行代码,并使您可以访问数据框中的内容。有关更多信息,您需要阅读文档,如果您想通过这种方式做,请仅让我知道

编辑: 这是代码

import pandas as pd
data = pd.read_csv('test.txt', sep=";")
data['sellerRating'].median()

答案 2 :(得分:0)

运行代码后,我得到以下结果:

raw results:
{'ClosePrice': 0.009999999999999998,
 'Duration': 5.6,
 'OpenPrice': 0.009999999999999998,
 'sellerRating': 3208.8}

Averages:
  sellerRating    3.208,80
  Duration            5,60
  ClosePrice          0,01
  OpenPrice           0,01

对于平均值来说哪个看起来正确,但是我相信您想要中位数,这是非常不同的。中位数是中间值,而不是总计/总和。中位数应该总是已经存在于数据集中。

您可以改为以某种数据结构收集值并找到中间值。一种简单的方法是使用collections.defaultdict()预先存储所有数据。想法是解析您的文件,将数据添加到defaultdict并在最后加上statistics.median()来获得中位数。

演示:

from csv import DictReader

from collections import defaultdict
from statistics import median

from locale import setlocale
from locale import LC_ALL
from locale import atof

setlocale(LC_ALL, 'Dutch_Netherlands.1252')

median_names = 'sellerRating', 'Duration', 'ClosePrice', 'OpenPrice'

data = defaultdict(list)
with open('data.txt') as f:
    csvreader = DictReader(f, delimiter=';')
    for dic in csvreader:
        for header, value in dic.items():
            data[header].append(value)

for median_name in median_names:
    med = median(map(atof, data[median_name]))
    print('{:<13} {:>10}'.format(median_name, med))

输出:

sellerRating      3249.0
Duration             5.0
ClosePrice          0.01
OpenPrice           0.01

由于所有这些值都存在于数据集中,因此现在将其作为中位数是有意义的。

您也可以使用原始数据集来格式化以上结果,以使其更加准确,但我将由您自己决定。