Pandas - 将CSV读入数据框,其中列具有不同数量的子列

时间:2017-07-31 21:29:45

标签: python pandas dataframe

在Pandas中,是否可以使用包含不同数量子列的列的数据框?

例如,假设我有这个CSV文件:

transactionId, userName, date, itemList, totalCost

其中itemList包含可变数量的itemId;itemPrice对,其中的对由管道(|)分隔。列表中itemId;itemPrice对的数量没有上限。

itemId ; itemPrice | itemId ; itemPrice

以下是行的一些示例:

transactionId, userName, date,       itemList,              totalCost
123,           Bob  ,    7/29/2017,  ABC;10|XYZ;20,         30
234,           Alice,    7/31/2017,  CDE;20|QRS;15|KLM;10,  45

第一行有两个itemId;itemPrice对,而第二行有三对。

如何创建包含此信息的数据框?我需要数据框内的数据框吗?

在可变数量的列上还有其他Stackoverflow帖子,但是they assume a maximum number of columns

2 个答案:

答案 0 :(得分:6)

我尝试规范化您的数据as proposed by @DYZ in comments

In [145]: df = df.join(df.pop('itemList')
     ...:                .str.extractall(r'(?P<item>\w+);(?P<price>\d+)')
     ...:                .reset_index(level=1, drop=True))
     ...:

In [146]: df
Out[146]:
   transactionId userName       date  totalCost item price
0            123      Bob  7/29/2017         30  ABC    10
0            123      Bob  7/29/2017         30  XYZ    20
1            234    Alice  7/31/2017         45  CDE    20
1            234    Alice  7/31/2017         45  QRS    15
1            234    Alice  7/31/2017         45  KLM    10

标准化数据允许我们应用Pandas / Numpy / SciPy /等。 u直接在包含标量值的列上运行。

演示:检查totalCost

df.price = pd.to_numeric(df.price, errors='coerce')

In [151]: df.assign(tot2=df.groupby(level=0).price.transform('sum'))
Out[151]:
   transactionId userName       date  totalCost item  price  tot2
0            123      Bob  7/29/2017         30  ABC     10    30
0            123      Bob  7/29/2017         30  XYZ     20    30
1            234    Alice  7/31/2017         45  CDE     20    45
1            234    Alice  7/31/2017         45  QRS     15    45
1            234    Alice  7/31/2017         45  KLM     10    45

In [152]: df.assign(tot2=df.groupby(level=0).price.transform('sum')).query("totalCost != tot2")
Out[152]:
Empty DataFrame
Columns: [transactionId, userName, date, totalCost, item, price, tot2]
Index: []

PS最后一个空DF显示我们没有totalCost != sum(price)

的任何条目

答案 1 :(得分:2)

您使用列表解析

解析它们
d1 = df.assign(
    itemList=[[x.split(';') for x in y.split('|')] for y in df.itemList.tolist()]
)

d1

   transactionId userName       date                           itemList  totalCost
0            123      Bob  7/29/2017             [[ABC, 10], [XYZ, 20]]         30
1            234    Alice  7/31/2017  [[CDE, 20], [QRS, 15], [KLM, 10]]         45

对评论的回应

f = lambda x: np.array(x)[:, 1].astype(int).sum()

d1.assign(sumPrice=d1.itemList.apply(f))

   transactionId userName       date                           itemList  totalCost  sumPrice
0            123      Bob  7/29/2017             [[ABC, 10], [XYZ, 20]]         30        30
1            234    Alice  7/31/2017  [[CDE, 20], [QRS, 15], [KLM, 10]]         45        45