Python 3.3.3 熊猫0.12.0
我有一个单列.csv文件,其中有数百个浮点值由任意字符串分隔(该字符串包含字母编辑:,并且将运行以运行)。我是一个熊猫初学者,希望找到一种方法来加载.csv文件并将浮点值分成两个列,在该字符串的水平。
我太困在第一部分(寻找字符串),我还没有能够在第二部分工作,我认为应该更容易。
到目前为止,我一直在尝试使用raw = pandas.read_csv('myfile.csv', squeeze=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
所需的最终DataFrame:
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]')
而不是使用.contains
来找到解决方案。
此时我的解决方案是只读取.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:使用itertools.groupby
的另一种可能解决方案:
import io
import itertools
import re
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""".splitlines()
groups = itertools.groupby(
txt,
key=lambda x: not re.match('^[\d.]+$', x)
)
df = pd.concat(
(pd.Series(list(g)) for k, g in groups if not k),
axis=1
)
print(df)
答案 0 :(得分:0)
如果您知道只有两列,那么您可以执行类似
的操作>>> 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模式,但如果没有它就可以逃脱,那就更好了。
(PS:我确信有比idxmax
更好的方法,但对于我的生活,我不记得现在找到第一个True的成语。split_at[split_at].index[0]
会这样做,但我不确定那会好得多。)
答案 1 :(得分:0)
使用numpy.split()
:
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