所以我有此CSV文件,我想执行以下操作:
原始数据:
已分析数据:
因此,用一句话来说,如果一列包含逗号,那么我想创建一个仅包含一个值的新列,并删除具有多个值的列。
例如:N2具有I1,I3和I4。因此,新数据将分为3列,仅包含一个值。
我想使它动态化,以反映所有排列。 就像N3具有2个地方和2个项目一样。
我正在尝试使用python的熊猫来做到这一点。一些帮助,将不胜感激。
答案 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'})
答案 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