Python 搜索系列中的值,并在该值处拆分系列
Python 3.3.3 熊猫0.12.0 我有一个单列.csv文件,其中有数百个浮点值,由一个任意字符串分隔(该字符串包含字母edit:并将随运行而变化)。我是一名熊猫初学者,希望找到一种加载.csv文件的方法,并在该字符串级别将浮点值拆分为两列 我被困在第一部分(搜索字符串)中,以致于我还不能处理第二部分,我认为这应该容易得多 到目前为止,我一直在尝试使用Python 搜索系列中的值,并在该值处拆分系列,python,csv,python-3.x,pandas,Python,Csv,Python 3.x,Pandas,Python 3.3.3 熊猫0.12.0 我有一个单列.csv文件,其中有数百个浮点值,由一个任意字符串分隔(该字符串包含字母edit:并将随运行而变化)。我是一名熊猫初学者,希望找到一种加载.csv文件的方法,并在该字符串级别将浮点值拆分为两列 我被困在第一部分(搜索字符串)中,以致于我还不能处理第二部分,我认为这应该容易得多 到目前为止,我一直在尝试使用raw=pandas.read_csv('myfile.csv',squeak=True),然后使用类似raw.str.findall('
raw=pandas.read_csv('myfile.csv',squeak=True)
,然后使用类似raw.str.findall('a-z'))
,但我运气不太好。如果有人能帮忙,我将不胜感激。我计划在许多类似的.csv文件上使用此过程,因此我希望找到一种相当自动化的方法来执行此任务
示例input.csv:
123.4932
239.348
912.098098989
49391.1093
....
This is a fake string that splits the data.
....
1323.4942
2445.34223
914432.4
495391.1093090
所需的最终数据帧:
Column A Column B
123.4932 1323.4942
239.348 2445.34223
912.098098989 914432.4
49391.1093 495391.1093090
... ...
如果你能给我指出正确的方向,再次感谢你
20131123 编辑:感谢您迄今为止的回复。更新以反映拆分字符串将不会保持不变,因此我声明我一直在尝试使用正则表达式
raw.str.findall('[a-z]')
而不是使用。来找到解决方案
此时,我的解决方案是读取.csv文件并使用re
进行拆分,累积到列表中,然后将其加载到pandas中
import pandas as pd
import re
raw = open('myfile.csv', 'r').read().split('\n')
df = pd.DataFrame()
keeper = []
counter = 0
# Iterate through the rows. Consecutive rows that can be made into float are accumulated.
for row in raw:
try:
keeper.append(float(row))
except:
if keeper:
df = pd.concat([df, pd.DataFrame(keeper, columns = [counter] )], axis = 1)
counter += 1
keeper = []
# Get the last column, assuming the file hasn't ended on a line
# that will trigger the exception in the above loop.
if keeper:
df = pd.concat([df, pd.DataFrame(keeper, columns = [counter] )], axis = 1)
df.describe()
谢谢你的进一步建议
20180729 EDIT2:另一种可能的解决方案,使用:
如果您知道只有两列,那么您可以执行以下操作
>>> ser = pd.read_csv("colsplit.csv", header=None, squeeze=True)
>>> split_at = ser.str.contains("fake string that splits").idxmax()
>>> parts = [ser[:split_at], ser[split_at+1:]]
>>> parts = [part.reset_index(drop=True) for part in parts]
>>> df = pd.concat(parts, axis=1)
>>> df.columns = ["Column A", "Column B"]
>>> df
Column A Column B
0 123.4932 ....
1 239.348 1323.4942
2 912.098098989 2445.34223
3 49391.1093 914432.4
4 .... 495391.1093090
5 NaN extra test element
如果您有任意数量的位置要拆分,那么您可以使用布尔级数/shift/cumsum/groupby模式,但是如果您可以不使用它,那就更好了
(注:我确信有一种比idxmax更好的方法,但就我的一生而言,我现在记不起这个成语来找到第一个正确的答案。split_at[split_at].index[0]
可以做到,但我不确定这是否更好。)使用numpy.split()
:
输出:
0 1 2
0 123.4932 1323.4942 31323.4942
1 239.348 2445.34223 42445.34223
2 912.098098989 914432.4 2914432.4
3 49391.1093 495391.1093090 5495391.1093090
4 NaN NaN 23423432
实际上,分隔符是什么?不幸的是,read_csv的lineterminator arg不允许您这样做(但?ValueError:只支持长度为1的行终止符
是的,不幸的是,pandas仍然无法处理非结构化的数据。在这种情况下,解决方案涉及文本编辑器或(更方便的)Unix命令行工具。这将是我的连续groupby的另一个使用案例,尽管没有它,我们可以轻松完成这一任务。实际的分隔符会有所不同,但始终是以几个单词开头的句子,可能是一些数字和符号。应始终使.match('\d+')
失败。
import io
import numpy as np
import pandas as pd
txt = """123.4932
239.348
912.098098989
49391.1093
This is a fake string that splits the data.
1323.4942
2445.34223
914432.4
495391.1093090
fake again
31323.4942
42445.34223
2914432.4
5495391.1093090
23423432"""
s = pd.read_csv(io.BytesIO(txt), header=None, squeeze=True)
mask = s.str.contains("fake")
pos = np.where(mask)[0]
pos -= np.arange(len(pos))
arrs = [s.reset_index(drop=True) for s in np.split(s[~mask], pos)]
pd.concat(arrs, axis=1, ignore_index=True).astype(float)
0 1 2
0 123.4932 1323.4942 31323.4942
1 239.348 2445.34223 42445.34223
2 912.098098989 914432.4 2914432.4
3 49391.1093 495391.1093090 5495391.1093090
4 NaN NaN 23423432