附加CSV文件,匹配无序列

时间:2015-01-12 22:50:12

标签: python csv pandas

问题:在附加CSV文件时匹配列

我有50个.csv文件,其中每列是一个单词,每行是一天中的一个时间,每个文件包含一天的所有单词。它们看起来像这样:

Date  Time Aword Bword Cword Dword
Date1 t1   0     1     0     12
Date1 t2   0     6     3     0

Date  Time Eword Fword Gword Hword Bword
Date2 t1   0     0     1     0     3
Date2 t2   2     0     0     19    0

我想附加文件,以便在新列中添加新单词时匹配具有相同单词的任何列(如本例中的Bword):

Date  Time Aword Bword Cword Dword Eword Fword Gword Hword
Date1 t1   0     1     0     12                       
Date1 t2   0     6     3     0                        
Date2 t1         3                 0     0     1     0   
Date2 t2         0                 2     0     0     19

我打开csv文件作为数据帧来操纵它们并使用dataframe.append新文件添加如下:

Date  Time Aword Bword Cword Dword
Date1 t1   0     1     0     12
Date1 t2   0     6     3     0
Date  Time Eword Fword Gword Hword Bword
Date2 t1   0     0     1     0     3
Dat2e t2   2     0     0     19    0

是否有一种不同的方法可以在追加时对齐匹配的列?即没有遍历每一列并检查匹配。

真诚的道歉,如果这个问题太模糊,我是python的新手,并且仍然在努力知道我什么时候以非诡计思考并且当我使用错误的工具时。

编辑:更多信息
1)我需要多次执行此任务,对于五批csvs中的每一批执行一次 2)文件都有25行,但有5到294列的任何内容 3)行的顺序是重要的Day1(t1,t2 ... tn)然后是Day2(t1,t2 ... tn)
4)列的顺序并不重要

3 个答案:

答案 0 :(得分:1)

我认为对于这种事情你可能会发现使用pandas库更容易一些。说filelist是文件名列表。

import pandas as pd

df = pd.concat([pd.read_csv(fl, index_col=[0,1]) for fl in filelist])

你已经完成了!作为旁注,如果您想组合日期和时间列(取决于其格式),您可以尝试

df = pd.concat([pd.read_csv(fl, parse_dates=['Date','Time']) for fl in filelist]).drop('Date', axis=1)

答案 1 :(得分:0)

IIUC,您只需使用pd.concat,它会自动在列上对齐:

>>> csvs = glob.glob("*.csv")
>>> dfs = [pd.read_csv(csv) for csv in csvs]
>>> df_merged = pd.concat(dfs).fillna("")
>>> df_merged
  Aword  Bword Cword   Date Dword Eword Fword Gword Hword Time
0     0      1     0  Date1    12                           t1
1     0      6     3  Date1     0                           t2
0            3        Date2           0     0     1     0   t1
1            0        Date2           2     0     0    19   t2

(虽然我建议使用fillna(0)或将其保留为nan;如果填充空字符串看起来像您想要的输出,则该列必须包含对象dtype且这些很多比int或float慢。)

如果您对列顺序非常了解,可以欺骗并使用(re)set_index

>>> df_merged.set_index(["Date", "Time"]).reset_index()
    Date Time Aword  Bword Cword Dword Eword Fword Gword Hword
0  Date1   t1     0      1     0    12                        
1  Date1   t2     0      6     3     0                        
2  Date2   t1            3                 0     0     1     0
3  Date2   t2            0                 2     0     0    19

答案 2 :(得分:0)

如果行和列的顺序不重要(如果是,则需要编辑Q以指定在文件中的顺序不同时如何处理它!),没有冲突(相同的值不同)相同日期和时间的列,以及数据适合内存 - 你更喜欢使用Python而不是Pandas(我注意到你没有用pandas标记你的Q) - 一种方法可能是以下内容:

import collections
import csv

def merge_csvs(*filenames):
    result_dict = collections.defaultdict(dict)
    all_columns = set()
    for fn in filenames:
        with open(fn) as f:
            dr = csv.DictReader(f)
            update_cols = True
            for row in dr:
                date = row.pop('Date')
                time = row.pop('Time')
                result_dict[date, time].update(row)
                if update_cols:
                    all_columns.update(row)
                    update_cols = False
    for d in result_dict:
        missing_cols = all_columns.difference(d)
        d.update(dict.from_keys(missing_cols, '')
    return result_dict

这产生了一个字典,由(date, time)对键控,字典,其键是在任何输入CSV中找到的所有列,具有该日期和时间的相应值,否则为空字符串该日期和时间从未找到该列。

现在你可以按照自己的意愿处理这个问题,例如

d = merge_csvs('a.csv', 'b.csv', 'c.csv')
for date, time in sorted(d):
    dd = d[date, time]
    outlist = [dd[c] for c in sorted(dd)]
    print(date, time, outlist)

或者,当然,将其写回不同的CSV,等等。