【问题标题】:Breaking Up CSV By Regex in Python在 Python 中通过正则表达式分解 CSV
【发布时间】:2014-03-12 09:27:28
【问题描述】:

我有一个格式如下的文件:

S1A23
0.01,0.01
0.02,0.02
0.03,0.03
S25A123
0.05,0.06
0.07,0.08
S3034A1
1000,0.04
2000,0.08
3000,0.1

我想将它按每个“S_A_”分解,并计算下面数据的相关系数。到目前为止,我有:

import re
import pandas as pd

test = pd.read_csv("predict.csv",sep=('S\d+A\d+'))

print test

但这只会给我:

  Unnamed: 0     ,
0  0.01,0.01  None
1  0.02,0.02  None
2  0.03,0.03  None
3        NaN     ,
4  0.05,0.06  None
5  0.07,0.08  None
6        NaN     ,
7  1000,0.04  None
8  2000,0.08  None
9   3000,0.1  None

[10 rows x 2 columns]

理想情况下,我希望保留正则表达式分隔符,并具有以下内容:

S1A23: 1.0
S2A123: 0.86
S303A1: 0.75

这可能吗?

编辑
运行大文件(~250k 行)时,我收到以下错误。数据没有问题,因为当我将大约 250k 行分成更小的块时,所有部分都运行良好。

Traceback (most recent call last):
  File "/Users/adamg/PycharmProjects/Subj_AnswerCorrCoef/GetCorrCoef.py", line 15, in <module>
    print(result)
  File "/Users/adamg/anaconda/lib/python2.7/site-packages/pandas/core/base.py", line 35, in __str__
    return self.__bytes__()
  File "/Users/adamg/anaconda/lib/python2.7/site-packages/pandas/core/base.py", line 47, in __bytes__
    return self.__unicode__().encode(encoding, 'replace')
  File "/Users/adamg/anaconda/lib/python2.7/site-packages/pandas/core/series.py", line 857, in __unicode__
    result = self._tidy_repr(min(30, max_rows - 4))
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

我的确切代码是:

import numpy as np
import pandas as pd
import csv
pd.options.display.max_rows = None
fileName = 'keyStrokeFourgram/TESTING1'

df = pd.read_csv(fileName, names=['pause', 'probability'])
mask = df['pause'].str.match('^S\d+_A\d+')
df['S/A'] = (df['pause']
              .where(mask, np.nan)
              .fillna(method='ffill'))
df = df.loc[~mask]

result = df.groupby(['S/A']).apply(lambda grp: grp['pause'].corr(grp['probability']))
print(result)

【问题讨论】:

    标签: python regex csv pandas


    【解决方案1】:

    sep 参数用于指定在同一行上分隔值的模式。它不能用于将 csv 的行分隔为单独的数据帧。

    编辑:有一种方法可以使用read_csv 将 csv 读入 DataFrame。由于read_csv should be faster,这比使用Python循环(如我的原始答案中所做的那样)更可取。这可能很重要——尤其是对于大型 csv 文件。

    import numpy as np
    import pandas as pd
    df = pd.read_csv("data", names=['x', 'y'])
    mask = df['x'].str.match('^S\d+A\d+')         # 1
    df['type'] = (df['x']
                  .where(mask, np.nan)            # 2
                  .fillna(method='ffill'))        # 3
    df = df.loc[~mask]                            # 4
    
    result = df.groupby(['type']).apply(lambda grp: grp['x'].corr(grp['y']))
    print(result)
    

    产量

    type
    S1A23      1.000000
    S25A123    1.000000
    S3034A1    0.981981
    dtype: float64
    

    1. 'x' 列中具有“类型”的行上的掩码为 True。

      In [139]: mask
      Out[139]: 
      0      True
      1     False
      2     False
      3     False
      4      True
      5     False
      6     False
      7      True
      8     False
      9     False
      10    False
      Name: x, dtype: bool
      
    2. df['x'].where(mask, np.nan) 返回一个系列,等于 df['x'] 其中 掩码为 True,否则为 np.nan。
    3. 用货币值向前填充nans

      In [141]: df['x'].where(mask, np.nan).fillna(method='ffill')
      Out[141]: 
      0       S1A23
      1       S1A23
      2       S1A23
      3       S1A23
      4     S25A123
      5     S25A123
      6     S25A123
      7     S3034A1
      8     S3034A1
      9     S3034A1
      10    S3034A1
      Name: x, dtype: object
      
    4. 仅选择掩码为 False 的行

    原答案:

    不幸的是,我看不到将您的数据文件直接读入适当的 DataFrame 的方法。您需要使用 Python 循环对行进行一些按摩以使其成为正确的形式。

    import pandas as pd
    import csv
    
    def to_columns(f):
        val = None
        for row in csv.reader(f):
            if len(row) == 1:
                val = row[0]
            else:
                yield [val] + row
    
    with open('data') as f:
        df = pd.DataFrame.from_records(to_columns(f), columns=['type', 'x', 'y'])
    
    print(df)
    result = df.groupby(['type']).apply(lambda grp: grp['x'].corr(grp['y']))
    print(result)
    

    【讨论】:

    • 感谢您的更新。不过,我确实有大量数据,而且它并没有打印出所有数据。我已经在 PyCharm 和终端中尝试过,但在这两种情况下它只打印几十个数据点,中间有一个“...”。知道如何获取所有数据吗?
    • pd.options.display.max_rows = None 放入您的脚本以查看所有行。键入 help(pd.set_option) 以查看可用选项。打印所有行的另一种方法是使用print(df.to_string())
    • 关于这个的两个后续问题,如果你不介意的话:1) 我怎样才能改变它以使用 Spearman 而不是 Pearson 相关性? 2) 当我尝试输入很多块 (~5k) 时出现错误。如果你愿意,我可以复制错误。
    • 1) 将 corr(grp['y']) 更改为 corr(grp['y'], method='spearman')。 2)请发布完整的回溯错误消息,以及您正在运行的代码。
    • 我添加了关于如何修复错误here的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    相关资源
    最近更新 更多