Python csv列的行名称并分配给列

时间:2016-06-14 05:58:58

标签: python csv pandas

我打赌有一种简单的方法可以做到这一点,但我无法弄明白。我有来自不同种族的一系列数据。问题在于所有数据都是合并的,并且有不同的单圈距离和时间。我想做的是动态地将数据输入到每个种族的列中。这是数据的粗略程度

  • 200m - 18.70 - (18.7)| 600m - 47.50 - (28.8)| 1000m - 1:16.62 - (29.1)| 1400m - 1:45.74 - (29.1)| 1800m - 2:14.95 - (29.2)| 2200m - 2:44.16 - (29.2)| 2600m - 3:13.27 - (29.1)| 3000m - 3:42.40 - (29.1)| 3400m - 4:11.70 - (29.3)| 3800m - 4:41.11 - (29.4)| 4200m - 5:10.75 - (29.6)| 4600m - 5:40.39 - (29.6)| 5000m - 6:10.44 - (30.0)|
  • 600m - 45.92 - (27.7)| 1000m - 1:16.24 - (30.3)|
  • 300m - 23.51 - (23.5)| 700m - 48.80 - (25.2)| 1100m - 1:14.96 - (26.1)| 1500m - 1:42.48 - (27.5)|

我知道所有可能的列,并且有42个。我想要的是行数据是否与列相同,以从该数据中获取时间。如果不在那个列中没有放任何东西。例如,第一个将在18毫米列中放置18.70-(18.7),在300米列中放置空值,在600米列中放置47.50-(28.8)等...最终从此创建一个稀疏的csv文件。

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

下面的工作解决方案。几个笔记:

  1. 我使用tablib,我最喜欢的库来处理CSV操作,natsort对列进行排序(" 300m"<" 2000m")
  2. 我通过获取数据每行中可用的所有种族的联合来发现了这组标题。你可以改为对该列表进行硬编码,因为你说你知道那里所有可能的值。
  3. 地图/条带/分区线可能令人困惑......分区调用在第一个min: 0.6, max: 300, step: 0.1, 上分裂,返回" - "(first_part, " - ", second_part)只会丢弃[::2]给我。然后我从剩下的部分中删除空白。
  4. 否则,希望代码是不言自明的:

    " - "

    输出:

    from natsort import natsorted
    import tablib
    
    data = '''200m - 18.70 - (18.7)|600m - 47.50 - (28.8)|1000m - 1:16.62 - (29.1)|1400m - 1:45.74 - (29.1)|1800m - 2:14.95 - (29.2)|2200m - 2:44.16 - (29.2)|2600m - 3:13.27 - (29.1)|3000m - 3:42.40 - (29.1)|3400m - 4:11.70 - (29.3)|3800m - 4:41.11 - (29.4)|4200m - 5:10.75 - (29.6)|4600m - 5:40.39 - (29.6)|5000m - 6:10.44 - (30.0)|
    600m - 45.92 - (27.7)|1000m - 1:16.24 - (30.3)|
    300m - 23.51 - (23.5)|700m - 48.80 - (25.2)|1100m - 1:14.96 - (26.1)|1500m - 1:42.48 - (27.5)|'''
    
    dictionaries = []
    headers = set()
    
    for row in data.split('\n'):
        row_dict = {}
        for entry in row.split('|'):
            column, value = map(str.strip, entry.partition(' - ')[::2])
            if column:
                row_dict[column] = value
        dictionaries.append(row_dict)
        headers.update(row_dict.keys())
    
    headers = natsorted(headers)
    dataset = tablib.Dataset(headers=headers)
    for row_dict in dictionaries:
        dataset.append([row_dict.get(header) for header in headers])
    
    with open('output.csv', 'wb') as f:
        f.write(dataset.csv)
    

答案 1 :(得分:0)

在离开互联网的时候,我还采取了一种“坐在问题中”的规范; - )

#! /usr/bin/env python
"""Learn by example - grass roots parser for kind of serialized
race reports, where records are separated by a pipe (|), fields
of result records separated y a dash (-) and some meaning is associated
with the fields per position in record."""
from __future__ import print_function


def parse_duration_string(text, min_sep=':'):
    """Simplistic parser, splitting duration sof minutes:seconds.fract
    into an ordered numerical pair of (integer, float). The minute portion
    is set to 0 if no min_sep is detected."""

    s_text = text.strip()
    minutes = 0
    if min_sep in s_text:
        min_cand, sec_cand = s_text.split(min_sep)
        minutes = int(min_cand)
        seconds = float(sec_cand)
    else:
        seconds = float(s_text)

    return minutes, seconds


def parse_sports_concat(text, token_set, rec_sep='|', field_sep='-'):
    """Split parse the text per record separator rec_sep,
    token in token_ser and subsequently split parse the associated
    result serialization (by field_sep) and use Occams razor
    against the noise ;-)."""

    shave_these = '( )'
    race_map = {}
    for record in text.split(rec_sep):
        s_record = record.strip()
        if not s_record:
            continue
        dist, in_secs, magic = s_record.split(field_sep)
        key = dist.strip()
        if key in token_set:
            if key not in race_map:
                race_map[key] = []
            race_map[key].append(
                (parse_duration_string(in_secs), magic.strip(shave_these)))
        else:
            print("Warning: Distance({0}) not found in TokenSet!".format(key))
    return race_map


def main():
    """Test drive the split, parse, map."""

    line_seq = (
        ('200m - 18.70 - (18.7)|600m - 47.50 - (28.8)|'
         '1000m - 1:16.62 - (29.1)|1400m - 1:45.74 - (29.1)|'
         '1800m - 2:14.95 - (29.2)|2200m - 2:44.16 - (29.2)|'
         '2600m - 3:13.27 - (29.1)|3000m - 3:42.40 - (29.1)|'
         '3400m - 4:11.70 - (29.3)|3800m - 4:41.11 - (29.4)|'
         '4200m - 5:10.75 - (29.6)|4600m - 5:40.39 - (29.6)|'
         '5000m - 6:10.44 - (30.0)|'),
        '600m - 45.92 - (27.7)|1000m - 1:16.24 - (30.3)|',
        ('300m - 23.51 - (23.5)|700m - 48.80 - (25.2)|'
         '1100m - 1:14.96 - (26.1)|1500m - 1:42.48 - (27.5)|'),
    )
    core_seq = (
        1, 2, 3, 3, 6, 7, 10, 11, 14, 15, 18, 22, 26,
        30, 34, 38, 42, 46, 50)
    token_seq = tuple('%dm' % (z * 100,) for z in core_seq)
    total_map = {}
    for line in line_seq:
        total_map.update(parse_sports_concat(line, set(token_seq)))

    for distance in token_seq:
        print('{0}: {1}'.format(distance,
                                total_map.get(distance, 'NotReported')))

if __name__ == '__main__':
    main()

的产率:

100m: NotReported
200m: [((0, 18.7), '18.7')]
300m: [((0, 23.51), '23.5')]
300m: [((0, 23.51), '23.5')]
600m: [((0, 45.92), '27.7')]
700m: [((0, 48.8), '25.2')]
1000m: [((1, 16.24), '30.3')]
1100m: [((1, 14.96), '26.1')]
1400m: [((1, 45.74), '29.1')]
1500m: [((1, 42.48), '27.5')]
1800m: [((2, 14.95), '29.2')]
2200m: [((2, 44.16), '29.2')]
2600m: [((3, 13.27), '29.1')]
3000m: [((3, 42.4), '29.1')]
3400m: [((4, 11.7), '29.3')]
3800m: [((4, 41.11), '29.4')]
4200m: [((5, 10.75), '29.6')]
4600m: [((5, 40.39), '29.6')]
5000m: [((6, 10.44), '30.0')]

它仅使用提供解析映射的字符串中的构建方法进行解析,通过多行合并的更新来扩展它,并将时间解析为一对整数分钟和浮点秒。第三个存档的dmagic按原样保留,但从括号中删除,因为这是非常安全地存储在固定的“插槽”中。

请注意,变量in_secs可能不是一个好名字,但谁知道。

您可以通过不调用parseduration_string()函数轻松地保留持续时间字符串。

享受Python学习之旅 - 上面的代码片段符合PEP8,这通常有助于Python领域了解这个PEP8和pythonic模式/习语,并从统一的代码读取中获益,帮助其他人直接进入问题区。

PS:在race_map中存在距离的先前测试的插入有点笨拙,但显而易见 - 特别是在开始学习语言时 - 比我想的更好。