如何使用Pandas读取包含逗号的数字的*.csv文件?

3
我将使用中文进行翻译,如下:

我想要读取一个包含逗号分隔数字的 *.csv 文件。

例如:

File.csv

Date, Time, Open, High, Low, Close, Volume
2016/11/09,12:10:00,'4355,'4358,'4346,'4351,1,201 # The last value is 1201, not 201
2016/11/09,12:09:00,'4361,'4362,'4353,'4355,1,117 # The last value is 1117, not 117
2016/11/09,12:08:00,'4364,'4374,'4359,'4360,10,175 # The last value is 10175, not 175
2016/11/09,12:07:00,'4371,'4376,'4360,'4365,590
2016/11/09,12:06:00,'4359,'4372,'4358,'4369,420
2016/11/09,12:05:00,'4365,'4367,'4356,'4359,542
2016/11/09,12:04:00,'4379,'1380,'4360,'4365,1,697 # The last value is 1697, not 697
2016/11/09,12:03:00,'4394,'4396,'4376,'4381,1,272 # The last value is 1272, not 272
2016/11/09,12:02:00,'4391,'4399,'4390,'4393,524
...
2014/07/10,12:05:00,'10195,'10300,'10155,'10290,219,271 # The last value is 219271, not 271
2014/07/09,12:04:00,'10345,'10360,'10185,'10194,235,711 # The last value is 235711, not 711
2014/07/08,12:03:00,'10339,'10420,'10301,'10348,232,050 # The last value is 242050, not 050

实际上,它有7列,但最后一列的某些值有逗号,而pandas会将它们视为额外的列。

我的问题是,如果有任何方法可以让pandas只读取前6个逗号并忽略其余的逗号,或者是否有任何方法可以删除第6个逗号之后的逗号(我很抱歉,我想不到任何可以做到这一点的功能)。

感谢您阅读这个 :)


1
引号是实际文件的一部分吗? - 3novak
你想只用pandas来完成这个任务吗?或者你也愿意尝试一些预处理的选项,然后将结果传递给pandas吗? - user2532296
你好。谢谢你的回答。我不仅可以在pandas中进行操作,也可以在其他地方进行操作。我正在查找一些字符串方法,但很难理解如何完成这项工作。 - maynull
另一种解决问题的方法。请查看下面的解决方案。 - Mohammad Yusuf
请编辑您的问题,准确地展示数据文件中的内容。 - John Machin
显示剩余4条评论
4个回答

2

您可以在Python中完成所有操作,而无需将数据保存到新文件中。其思路是将数据清理并以类似字典的格式放入pandas中以便于转换为数据框。以下应该构成一个不错的起点:

from collections import defaultdict
from collections import OrderedDict
import pandas as pd

# Import the data
data = open('prices.csv').readlines()

# Split on the first 6 commas
data = [x.strip().replace("'","").split(",",6) for x in data]

# Get the headers
headers = [x.strip() for x in data[0]]

# Get the remaining of the data
remainings = [list(map(lambda y: y.replace(",",""), x)) for x in data[1:]]

# Create a dictionary-like container
output = defaultdict(list)

# Loop through the data and save the rows accordingly
for n, header in enumerate(headers):
    for row in remainings:
        output[header].append(row[n])

# Save it in an ordered dictionary to maintain the order of columns
output = OrderedDict((k,output.get(k)) for k in headers)
# Convert your raw data into a pandas dataframe
df = pd.DataFrame(output)

# Print it
print(df)

这将产生:
         Date      Time  Open  High   Low Close Volume
0  2016/11/09  12:10:00  4355  4358  4346  4351   1201
1  2016/11/09  12:09:00  4361  4362  4353  4355   1117
2  2016/11/09  12:08:00  4364  4374  4359  4360  10175
3  2016/11/09  12:07:00  4371  4376  4360  4365    590
4  2016/11/09  12:06:00  4359  4372  4358  4369    420
5  2016/11/09  12:05:00  4365  4367  4356  4359    542
6  2016/11/09  12:04:00  4379  1380  4360  4365   1697
7  2016/11/09  12:03:00  4394  4396  4376  4381   1272
8  2016/11/09  12:02:00  4391  4399  4390  4393    524

起始文件(prices.csv)如下所示:
Date, Time, Open, High, Low, Close, Volume
2016/11/09,12:10:00,'4355,'4358,'4346,'4351,1,201
2016/11/09,12:09:00,'4361,'4362,'4353,'4355,1,117
2016/11/09,12:08:00,'4364,'4374,'4359,'4360,10,175
2016/11/09,12:07:00,'4371,'4376,'4360,'4365,590
2016/11/09,12:06:00,'4359,'4372,'4358,'4369,420
2016/11/09,12:05:00,'4365,'4367,'4356,'4359,542
2016/11/09,12:04:00,'4379,'1380,'4360,'4365,1,697
2016/11/09,12:03:00,'4394,'4396,'4376,'4381,1,272
2016/11/09,12:02:00,'4391,'4399,'4390,'4393,524

我希望这能有所帮助。

谢谢你的回答,Abdou!这个方法非常直接,让我能够解决问题,并且教会了我使用Python的新方法。我很感激! - maynull
我很高兴这个有用。 - Abdou

1

我猜pandas无法处理它,所以我会使用Perl进行预处理来生成新的cvs并在其上工作。

使用Perl的split可以在这种情况下帮助你。

perl -pne '$_ = join("|", split(/,/, $_, 7) )' < input.csv > output.csv

然后您可以使用通常的read_csv函数读取以|为分隔符的输出文件。


谢谢你,Astish Sai!我对Perl不是很了解,但如果我有大量的数据需要处理,我认为它是最简单的方法! - maynull
@maynull 我很高兴能够帮助你。如果你认为这个解决方案适用于你提到的问题,请务必打勾标记答案,以便其他人也能受益。 - Aatish Sai

1
一种解决您问题的方法。
import re
import pandas as pd

l1 =[]
with open('/home/yusuf/Desktop/c1') as f:
    headers = map(lambda x: x.strip(), f.readline().strip('\n').split(','))
    for a in f.readlines():
        b = re.findall("(.*?),(.*?),'(.*?),'(.*?),'(.*?),'(.*?),(.*)",a)
        l1.append(list(b[0]))
df = pd.DataFrame(data=l1, columns=headers)
df['Volume'] = df['Volume'].apply(lambda x: x.replace(",",""))
df

输出:

enter image description here

正则表达式演示:
https://regex101.com/r/o1zxtO/2


1
这看起来像是第3、4、5和8行有问题,例如第3行的close == 4365.590和volume == 0,但应该是close 4365和volume 590。 - John Machin
@JohnMachin 哦,我的错。我误读了他的问题。现在它甚至比那更简单。我已经纠正了它。 - Mohammad Yusuf

1
我相信pandas无法处理这个问题,但你可以轻松地解决最后一列。以下是Python的方法:
    with open('yourfile.csv') as csv, open('newcsv.csv','w') as result:
        for line in csv:
            columns = line.split(',')
            if len(columns) > COLUMNAMOUNT:
                columns[COLUMNAMOUNT-1] += ''.join(columns[COLUMNAMOUNT:])
            result.write(','.join(columns[COLUMNAMOUNT-1]))

现在你可以将新的csv加载到pandas中。其他解决方案可以是AWK甚至是shell脚本。

感谢您的帮助,kabanus!多亏了您,我决定更深入地学习csv库。这是一个非常简单的方法,易于理解其逻辑。再次感谢您! - maynull
1
你也可以使用上下文管理器打开 result 文件,将变量命名为标准库模块的名称总是有风险的。如果以后想要使用 csv 模块,这可能会导致问题。 - Maarten Fabré
@MaartenFabré,我最近才开始使用它,感觉它有点过头了,但我会接受。有没有办法在同一个 with 语句中定义多个变量?NM找到了。 - kabanus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接