在python中更改CSV文件

时间:2013-08-29 18:32:21

标签: python csv pandas glob

我有一堆带有4个标题的CSV文件。在这些文件中,我想根据第二列中的值更改第六列中的值。例如,如果名为PRODUCT的第二列为Banana,我希望将TIME下的同一行中的值更改为10m。如果产品为Apple,我希望时间为15m,依此类推。

When    12:07           
Area    Produce             
Store Name   FF             
Eatfresh                    
PN  PRODUCT NUMBER  INV ENT TIME
1    Banana 600000                5m
2    Apple  400000       F4        8m                                              
3    Pair                       6m
4    Banana 4000     G3            7m
5    Watermelon 700000          13m
6    Orange 12000               2m
7    Apple  1650000         6m

所需输出

When    12:07           
Area    Produce             
Store Name   FF             
Eatfresh                    
PN  PRODUCT NUMBER  INV ENT TIME
1    Banana 600000                10m
2    Apple  400000       F4        15m                                              
3    Pair                       6m
4    Banana 4000     G3            10m
5    Watermelon 700000          13m
6    Orange 12000               2m
7    Apple  1650000         15m

我想将所有这些输出输出到目录调用NTime。这是我到目前为止所做的,但对编码不熟悉,我真的不太了解并且已经陷入了如何进行实际更改的问题。我找到了Python/pandas idiom for if/then/else,它似乎与我想做的相似,但我并不完全理解发生了什么。

import pandas as pd
import glob
import os

fns = glob.glob('*.csv') 
colname1 = 'PRODUCT'
colname2 = 'TIME'

for csv in fns:
    s = pd.read_csv(csv, usecols=[colname1], squeeze=True, skiprows=4, header=0)



    with open(os.path.join('NTime', fn), 'wb') as f:

有人可以帮助我吗?

2 个答案:

答案 0 :(得分:1)

您可以结合使用groupbyreplacedict

来执行此操作
In [76]: from pandas import DataFrame

In [77]: fruits = ['banana', 'apple', 'pear', 'banana', 'watermelon', 'orange', 'apple']

In [78]: times = ['5m', '8m', '6m', '7m', '13m', '2m', '6m']

In [79]: time_map = {'banana': '10m', 'apple': '15m', 'pear': '5m'}

In [80]: df = DataFrame({'fruits': fruits, 'time': times})
Out[80]:
       fruits time
0      banana   5m
1       apple   8m
2        pear   6m
3      banana   7m
4  watermelon  13m
5      orange   2m
6       apple   6m

In [81]: def replacer(g, time_map):
   ....:     tv = g.time.values
   ....:     return g.replace(to_replace=tv, value=time_map.get(g.name, tv))

In [82]: df.groupby('fruits').apply(replacer, time_map)
Out[82]:
       fruits time
0      banana  10m
1       apple  15m
2        pear   5m
3      banana  10m
4  watermelon  13m
5      orange   2m
6       apple  15m

你说你是编程的新手,所以我会解释发生了什么。

  1. df.groupby('fruits')使用DataFrame列的值将DataFrame拆分为子集(Seriesfruits个对象)。< / p>

  2. apply方法将函数应用于上述每个子集并连接结果(如果需要)。

  3. replacer是“神奇”发生的地方:每个组的time值都被替换为to_replace),其中 new 值定义于time_mapget的{​​{1}}方法允许您提供默认值,如果您搜索的密钥(在这种情况下为水果名称)不存在。 dict通常用于此目的,但在这里我实际上只是使用已经存在的时间,如果在nan time_map中没有为其定义新的时间。

  4. 有一点需要注意的是我对dict的使用。这通常不作为g.name上的属性存在(如果您愿意,您当然可以自己定义),但是在那里您可以执行可能需要组名的计算。在这种情况下,这是您在应用函数时所看到的“当前”水果。

    如果您为每个水果设置了新值,或者您手动用旧值写入,则可以将其缩短为单行:

    DataFrame

答案 1 :(得分:0)

假设您的数据位于Pandas DataFrame中,看起来像这样:

PN  PRODUCT NUMBER  INV ENT TIME
1    Banana 600000                10m
2    Apple  400000       F4        15m                                              
3    Pair                       6m
4    Banana 4000     G3            10m
5    Watermelon 700000          13m
6    Orange 12000               2m
7    Apple  1650000         15m

然后你应该能够使用这样的简单循环基于另一列(同一行)中的值来操作一列中的值:

for numi, i in enumerate(df["PRODUCT"]):
    if i == "Banana":
        df["TIME"][numi] = "10m"
    if i == "Apple":
        df["TIME"][numi] = "15m"

代码首先循环遍历数据框列“PRODUCT”的行,行值存储为i,行号存储为numi。然后,它使用if语句来标识“产品”列中不同的兴趣级别。对于具有感兴趣级别的行(例如“Banana”或“Apple”),它使用行号来更改同一行中另一列的值。

有很多方法可以做到这一点,并且根据您要更改的数据大小和级别数(在本例中为“产品”),这不一定是最有效的方法。但既然你是初学者,这可能是一个很好的基本方式,让你开始。