在python中解析CSV的特定列

时间:2019-02-24 16:59:47

标签: python pandas csv

所以我有此CSV文件,我想执行以下操作:

原始数据:

enter image description here

已分析数据:

enter image description here

因此,用一句话来说,如果一列包含逗号,那么我想创建一个仅包含一个值的新列,并删除具有多个值的列。

  

例如:N2具有I1,I3和I4。因此,新数据将分为3列,仅包含一个值。

我想使它动态化,以反映所有排列。 就像N3具有2个地方和2个项目一样。

我正在尝试使用python的熊猫来做到这一点。一些帮助,将不胜感激。

5 个答案:

答案 0 :(得分:1)

这是另一种选择:

df['Place'] = df['Place'].str.split(',')
df['Item'] = df['Item'].str.split(',')

exploded = pd.DataFrame([
    a + [p, t] for *a, P, T in df.values
    for p in P for t in T
], columns=df.columns)

输出:

  Name Place Item
0   N1    P1   I1
1   N2    P2   I1
2   N2    P2   I3
3   N2    P2   I4
4   N3    P2   I2
5   N3    P2   I5
6   N3    P3   I2
7   N3    P3   I5

答案 1 :(得分:0)

这是一个解决方案

split_place = df['Place'].str.split(',', expand=True)\
    .stack().str.strip().reset_index(level=1, drop=True)
split_item = df['Item'].str.split(',', expand=True)\
    .stack().str.strip().reset_index(level=1, drop=True)

df_temp = df[['Name']].merge(
    split_place.rename('split_place'), 
    left_index=True, 
    right_index=True, 
    how='outer'
)

exploded_df = df_temp.merge(
    split_item.rename('split_item'), 
    left_index=True, right_index=True, 
    how='outer'
).reset_index(drop=True)\
.rename(columns={'new_x': 'Place', 'new_y': 'Item'})

PS:您需要熊猫v0.24.0,否则合并将无法在此处进行。 enter image description here

答案 2 :(得分:0)

您实际上是在尝试获取每一行的笛卡尔积,然后将结果绑定回DataFrame中。因此,您可以使用itertools并执行类似的操作

from itertools import chain, product
df_lists = df.applymap(lambda s: s.split(','))
pd.DataFrame(chain.from_iterable(df_lists.apply(lambda row: product(*row), axis=1)), columns=df.columns)

在您的示例输入中:

In [334]: df
Out[334]:
  Name  Place      Item
0   N1     P1        I1
1   N2     P2  I1,I3,I4
2   N3  P2,P3     I2,I5

In [336]: df_lists = df.applymap(lambda s: s.split(','))

In [337]: pd.DataFrame(chain.from_iterable(df_lists.apply(lambda row: product(*row), axis=1)), columns=df.columns)
Out[337]:
  Name Place Item
0   N1    P1   I1
1   N2    P2   I1
2   N2    P2   I3
3   N2    P2   I4
4   N3    P2   I2
5   N3    P2   I5
6   N3    P3   I2
7   N3    P3   I5

答案 3 :(得分:0)

您可以使用iterrows()

df = pd.DataFrame({'Name': ['N1', 'N2', 'N3'], 'Place':['P1', 'P2','P2,P3'], 'Item':['I1,', 'I1,I3,I4', 'I2,I5']})

result = pd.DataFrame()
new_result = pd.DataFrame()

df['Place'] = df['Place'].apply(lambda x: x.strip(','))
df['Item'] = df['Item'].apply(lambda x: x.strip(','))

for a,b  in df.iterrows():
    curr_row = df.iloc[a]
    temp  = ((curr_row['Place'].split(',')))
    for x in temp:
        curr_row['Place'] = x
        result = result.append(curr_row, ignore_index=True)

for a,b  in result.iterrows():
    curr_row = result.iloc[a]
    temp  = ((curr_row['Item'].split(',')))
    for x in temp:
        curr_row['Item'] = x
        new_result = new_result.append(curr_row, ignore_index=True)

输出:

  Name Place Item
0   N1    P1   I1
1   N2    P2   I1
2   N2    P2   I3
3   N2    P2   I4
4   N3    P2   I2
5   N3    P2   I5
6   N3    P3   I2
7   N3    P3   I5

这是获得所需输出的最简单方法。

答案 4 :(得分:0)

您可以避免使用熊猫。如果您想使用标准的csv模块,则只需在逗号(',')上拆分每个字段,然后对拆分后的元素进行迭代。

代码可能是假设输入分隔符是分号(;不知道它是什么,除了它不能是逗号):< / p>

with open('input.csv', newline='') as fd, open('output.csv', 'w', newline='') as fdout:
    rd = csv.DictReader(fd, delimiter=';')
    wr = csv.writer(fdout)
    _ = wr.writerow(rd.fieldnames)
    for row in rd:
       for i in row['Item'].split(','):
           i = i.strip()
           if len(i) != 0:
               for p in row['Place'].split(','):
                   p = p.strip()
                   if len(p) != 0:
                       for n in row['Name'].split(','):
                           n = n.strip()
                           if len(n) != 0:
                               wr.writerow((n,p,i))

输出为:

Name,Place,Item
N1,P1,I1
N2,P2,I1
N2,P2,I3
N2,P2,I4
N3,P2,I2
N3,P3,I2
N3,P2,I5
N3,P3,I5