为什么我的pandas DataFrame列也是DataFrame而不是Series?

3

结尾更新 结尾更新2

我从这里阅读到: 从 Pandas 数据帧列中获取列表

Pandas DataFrame 列在提取时是 Pandas Series

然而,在我的情况下,这不是真的:

第一部分(构建读取 json 爬取的 DataFrame) 由于它包含商业信息,我无法显示完整代码,但基本上它读取一行数据(存储在 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'

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

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

我发现我需要使用.value.tolist(),然而这仍然不能解释为什么当我取出一列时我得到另一个Dataframe而不是Series。

更新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']], labels=[[4, 7, 5, 6, 1, 8, 3, 0, 2]])

我在打印df /写入.csv时看不到labels,它只是一个普通的DataFrame。不确定我从哪里得到了这些标签。

2个回答

7

我认为你有重复的列名,如果想要选择 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)时,它不显示任何标签。我将在问题中更新标签。 - Nicholas Humphrey
1
@NicholasHumphrey - 是的,如果是 MultiIndex,那么意味着第一层重复 :) - jezrael
谢谢,终于找到问题的根源了。顺便说一下,我不应该有多重索引,所以我会想办法找到它的来源。 - Nicholas Humphrey
1
@NicholasHumphrey - 为您的情况添加了解决方案。 - jezrael
1
谢谢!我明天早上会看一下,但我觉得它应该能够工作。现在的下一步是找到MultiIndex的源代码... - Nicholas Humphrey
1
@NicholasHumphrey - 是的,这种错误非常不愉快,特别是在打印DataFrame时看不到。 - jezrael

1
每个 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 - Nicholas Humphrey
1
@jezrael的回答表明可能存在重复列,请尝试运行print(df.columns)并查看列标题的命名,也许有两个相同的字符串。 - NiallJG
谢谢,是的,我发现有MultiIndex,我会检查以前的代码找到它的来源。 - Nicholas Humphrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接