为啥我的 pandas DataFrame 列也是 Dataframes,而不是 Series?

Posted

技术标签:

【中文标题】为啥我的 pandas DataFrame 列也是 Dataframes,而不是 Series?【英文标题】:Why are my pandas DataFrame columns Dataframes too, not Series?为什么我的 pandas DataFrame 列也是 Dataframes,而不是 Series? 【发布时间】:2019-06-02 19:11:37 【问题描述】:

最后更新 最后更新 2

我从这里读到: get list from pandas dataframe column

Pandas DataFrame 列在拉出时是 Pandas Series

但在我的情况下这不是真的:

第一部分(构建 DataFrame 读取 json 抓取) 因为它包含业务信息,所以我无法显示完整的代码,但基本上它读取一行数据(存储在 Series 中)并附加在 DataFrame 的末尾。

dfToWrite = pandas.DataFrame(columns=[lsHeader]) # Empty with column headers
for row in jsAdtoolJSON['rows']:
    lsRow = []
    for col in row['row']:
        lsRow.append((col['primary'])['value'])
    dfRow = pandas.Series(lsRow, index = dfToWrite.columns)
dfToWrite = dfToWrite.append(dfRow, ignore_index = True)

下一部分(检查类型):(请忽略函数的功能)

def CalcMA(df: pandas.DataFrame, target: str, period: int, maname: str):
    print(type(df[target]))

最后调用函数:(“Raw_Impressions”是列标题)

CalcMA(dfToWrite, "Raw_Impressions", 5, "ImpMA5")

Python 控制台显示:

类'pandas.core.frame.DataFrame'

附加问题:如果不是系列,如何从数据框列中获取列表(在这种情况下我可以使用tolist())?

更新 1 从这里: Bokeh: AttributeError: 'DataFrame' object has no attribute 'tolist'

我发现我需要使用.value.tolist(),但它仍然无法解释为什么当我拉出一列时我得到的是另一个数据框,而不是一个系列。

更新 2 发现df有MultiIndex,很惊讶:

MultiIndex(levels=[['COST_/CPM', 'CTR', 'ECPM/_ROI', 'Goal_Ratio', 'Hour_of_the_Day', 'IMP./Joins', 'Raw_Clicks_/ _Unique_Clicks'、'Raw_Impressions'、'Unique_Goal_/_UniqueGoal_Forecasted_Value']]、 标签=[[4, 7, 5, 6, 1, 8, 3, 0, 2]])

打印出 df / 写入 .csv 时,我看不到 labels,它只是一个普通的 DataFrame。不知道我从哪里得到的标签。

【问题讨论】:

【参考方案1】:

我认为你有重复的列名,所以如果要选择Series 获取DataFrame

df = pd.DataFrame([[1,2],[4,5], [7,8]], index=list('aab')).T
print (df)
   a  a  b
0  1  4  7
1  2  5  8

print (df['a'])
   a  a
0  1  4
1  2  5

print (type(df['a']))
<class 'pandas.core.frame.DataFrame'>

print (df['b'])
0    7
1    8
Name: b, dtype: int64

print (type(df['b']))
<class 'pandas.core.series.Series'>

编辑:

这是另一个问题,一级MultiIndex,解决方案是将一级重新分配给get_level_values的列:

mux = pd.MultiIndex([['COST_/CPM', 'CTR', 'ECPM/_ROI', 'Goal_Ratio', 'Hour_of_the_Day', 
                      'IMP./Joins',  'Raw_Clicks_/_Unique_Clicks', 'Raw_Impressions',
                      'Unique_Goal_/_UniqueGoal_Forecasted_Value']], 
labels=[[4, 7, 5, 6, 1, 8, 3, 0, 2]])

df = pd.DataFrame([range(9)], columns=mux)
print (type(df['CTR']))
<class 'pandas.core.frame.DataFrame'>

df.columns = df.columns.get_level_values(0)
print (type(df['CTR']))
<class 'pandas.core.series.Series'>

【讨论】:

谢谢@jezrael,刚刚打印出列,发现实际上我有一个MultiIndex,它会导致问题吗? (levels 没有重复)这很奇怪,因为当我 print(df) 它没有显示任何标签。我会用标签更新问题。 @NicholasHumphrey - 是的,如果 MultiIndex 则意味着第一级重复:) @NicholasHumphrey - 为您的情况添加了解决方案。 谢谢!我会在早上看看,但我认为它会工作。现在下一步就是追查MultiIndex的来源... @NicholasHumphrey - 是的,这种错误非常令人不快,尤其是因为在打印 DataFrame 时没有看到。【参考方案2】:

pandas.core.frame.DataFrame 的每个实例基本上都是一个数组,因此如果您要获取此类型,则可以通过调用 df.columns 来获取每一列(如果该列是一维的,则类型为 pandas.core.series.Series)。

df.columns 将为您提供一个可迭代对象,您可以循环访问该对象以获取每一行的值。

您可能还想查看pandas.read_json 或其他类似的包,以便将json 直接放入可能更易于管理的pandas 对象中

【讨论】:

感谢@NiallJG 我设法使用df(target).values.tolist() 从列中获取列表。但它仍然让我感到困惑为什么df(target),其中target 只是一个字符串,不代表Series @jezrael 的回答表明可能有重复的列,尝试运行 print(df.columns) 并查看列标题的名称,可能有两个相同的字符串 谢谢,我发现有multiindex,我会检查以前的代码找到它的来源。

以上是关于为啥我的 pandas DataFrame 列也是 Dataframes,而不是 Series?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在我遍历 pandas DataFrame 后这个函数不“接受”?

为啥在具有一级索引的 MultiIndex 列的 pandas DataFrame 中表现不同?

为啥我的 Pandas 引用多个列的“应用”函数不起作用? [关闭]

为啥我的代码没有从 Pandas 数据框中选择数据? [复制]

为啥Pandas的DataFrame使用Series而非直接使用矩阵进行存储和数据操纵?

Pandas DataFrame:set_index with inplace=True 返回 NoneType,为啥?