pandas 解析 Dataframe 中未对齐的列

0aydgbwb  于 2023-02-14  发布在  其他
关注(0)|答案(2)|浏览(168)

我有原始csv格式的源数据,其中有些列不对齐,有些根本没有某些列。所需的数据可以位于1-30列中的任何一列。找到数据所在位置的主要关键是每个子帧的标题中显示“1年成本”。
源数据示例:

import pandas as pd
from io import StringIO

sourceCSV = """col0,col1,col2,col3,col4,col5,col6
,,Cost,1 Mn Cost,1 Yr Cost,,
,Michigan,$50 ,$55 ,$65 ,,
,,,,Cost,1 Mn Cost,1 Yr Cost
,,,Indiana,$40 ,$45 ,$55 
,Cost,1 Mn Cost,1 Yr Cost,,,
New York,$25 ,$30 ,$35 ,,,
,,Cost,1 Yr Cost,,,
,Florida,$10 ,$20 ,,,"""

csvStringIO = StringIO(sourceCSV)
dfSource = pd.read_csv(csvStringIO, sep=",", header=None)

| 颜色0|列1|列2|第3栏|第4栏|第5栏|第6列|
| - ------|- ------|- ------|- ------|- ------|- ------|- ------|
| 零|零|费用|1百万成本|1年成本|零|零|
| 零|密歇根州|五十|五十五|六十五|零|零|
| 零|零|零|零|费用|1百万成本|1年成本|
| 零|零|零|印第安纳州|四十|四十五|五十五|
| 零|费用|1百万成本|1年成本|零|零|零|
| 纽约|二十五|三十|三十五|零|零|零|
| 零|零|费用|1年成本|零|零|零|
| 零|佛罗里达|十个|二十个|零|零|零|
我需要解析数据,并以类似下面的格式获取数据:
| 位置|费用|1百万成本|1年成本|
| - ------|- ------|- ------|- ------|
| 密歇根州|五十元|五十五元|六十五元|
| 印第安纳州|四十元|四十五元|五十五元|
| 纽约|二十五元|三十元|三十五元|
| 佛罗里达|十元|零|二十元|
我唯一能想到的是手动循环遍历每一列,但这是非常低效的,完成这一点的最佳方法是什么?

0s7z1bwu

0s7z1bwu1#

在特定情况下,一种可能性是:

  • 将奇数行视为标题,将偶数行视为数据
  • 在第一个单元格中添加“位置”
  • 堆栈以删除NaN
  • 再成形
dfSource = pd.read_csv(csvStringIO, sep=",", skiprows=1, header=None)

(dfSource[0].where(dfSource.index%2==1, 'Location').to_frame()
  .join(dfSource.iloc[:, 1:]) 
  .set_index([dfSource.index//2, dfSource.index%2])
  .stack().droplevel(-1).to_frame('value')
  .pipe(lambda d: d.set_index(d.groupby(level=[0, 1]).cumcount(), append=True))
  .unstack(1).droplevel(1)['value']
  .pivot(columns=0, values=1)
)

输出:

0 1 Mn Cost 1 Yr Cost  Cost  Location
0      $55       $65   $50   Michigan
1      $45       $55   $40    Indiana
2      $30       $35   $25   New York
3       NaN      $20   $10    Florida
nx7onnlm

nx7onnlm2#

格式错误的数据集有一些"对齐",即包含所需列和值的行是成对的,但 * location * 值除外,该值有向左偏移,需要单独捕获。
开始加载csv,跳过不需要的col0 col1 col2 ....的第1行:

df = pd.read_csv(csvStringIO, sep=",", header=None, skiprows=1)

然后,我们进行一个简短的处理(对行进行分组,并分别收集列和值):
x一个一个一个一个x一个一个二个x

相关问题