从 pandas 数据框的列或行获取列表?
- 2025-01-16 08:37:00
- admin 原创
- 76
问题描述:
我有一个df
从 Excel 文档导入的数据框,如下所示:
cluster load_date budget actual fixed_price
A 1/1/2014 1000 4000 Y
A 2/1/2014 12000 10000 Y
A 3/1/2014 36000 2000 Y
B 4/1/2014 15000 10000 N
B 4/1/2014 12000 11500 N
B 4/1/2014 90000 11000 N
C 7/1/2014 22000 18000 N
C 8/1/2014 30000 28960 N
C 9/1/2014 53000 51200 N
我希望能够将第 1 列的内容df['cluster']
作为列表返回,这样我就可以在其上运行 for 循环,并为每个集群创建一个 Excel 工作表。
是否也可以将整列或整行的内容返回到列表?例如
list = [], list[column1] or list[df.ix(row1)]
解决方案 1:
当您将 Pandas DataFrame 列拉出时,它们就是 Pandas Series,然后您可以调用x.tolist()
它来将它们转换为 Python 列表。或者,您可以使用 进行转换list(x)
。
import pandas as pd
data_dict = {'one': pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two': pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(data_dict)
print(f"DataFrame:
{df}
")
print(f"column types:
{df.dtypes}")
col_one_list = df['one'].tolist()
col_one_arr = df['one'].to_numpy()
print(f"
col_one_list:
{col_one_list}
type:{type(col_one_list)}")
print(f"
col_one_arr:
{col_one_arr}
type:{type(col_one_arr)}")
输出:
DataFrame:
one two
a 1.0 1
b 2.0 2
c 3.0 3
d NaN 4
column types:
one float64
two int64
dtype: object
col_one_list:
[1.0, 2.0, 3.0, nan]
type:<class 'list'>
col_one_arr:
[ 1. 2. 3. nan]
type:<class 'numpy.ndarray'>
解决方案 2:
这将返回一个 numpy 数组:
arr = df["cluster"].to_numpy()
这将返回唯一值的 numpy 数组:
unique_arr = df["cluster"].unique()
您也可以使用 numpy 来获取唯一值,尽管这两种方法之间存在差异:
arr = df["cluster"].to_numpy()
unique_arr = np.unique(arr)
解决方案 3:
转换示例:
Numpy 数组 -> Panda 数据框 -> 来自一个 Panda 列的列表
Numpy 数组
data = np.array([[10,20,30], [20,30,60], [30,60,90]])
将 numpy 数组转换为 Panda 数据框
dataPd = pd.DataFrame(data = data)
print(dataPd)
0 1 2
0 10 20 30
1 20 30 60
2 30 60 90
将一个 Panda 列转换为列表
pdToList = list(dataPd['2'])
解决方案 4:
以下是简单的一行代码:
list(df['load_date'])
更新: toList() 不起作用。它应该全部小写。tolist()
解决方案 5:
TL;DR:使用.tolist()
。不要使用list()
如果我们看一下源代码.tolist()
,就会发现在底层,list()
函数正在对数据框中的底层数据进行调用,因此两者都应该产生相同的输出。
但是,它似乎tolist()
针对 Python 标量的列进行了优化,因为我发现调用list()
列比调用慢 10 倍tolist()
。顺便说一句,我试图将非常大的数据框中的一列 json 字符串转换为列表,并且list()
花费了不少时间。这启发了我测试这两种方法的运行时间。
仅供参考,无需调用.to_numpy()
或获取.values
属性,因为数据框列/Series 对象已经实现了.tolist()
方法。此外,由于 numpy 数组的存储方式,list()
并且tolist()
会为数字列提供不同类型的标量(至少)。例如,
type(list(df['budget'].values)[0]) # numpy.int64
type(df['budget'].values.tolist()[0]) # int
以下 perfplot 显示了两种方法在各种 pandas dtype Series 对象上的运行时差异。基本上,它显示了以下两种方法之间的运行时差异:
list(df['some_col']) # list()
df['some_col'].tolist() # .tolist()
如您所见,无论列/系列的大小如何,对于数字和对象数据类型的列/系列,.tolist()
方法都比快得多。这里没有包括,但和数据类型列list()
的图表与此处显示的数据类型列的图表非常相似。此外,包含列表的对象数据类型列的图表与此处显示的字符串列的图表非常相似。扩展数据类型(例如、等)也显示出类似的模式。float
`boolint
'Int64Dtype''StringDtype'
'Float64Dtype'`
另一方面,对于datetime
、timedelta
和Categorical
dtype 列,这两种方法几乎没有区别。
绘制上述图表所用的代码:
from perfplot import plot
kernels = [lambda s: list(s), lambda s: s.tolist()]
labels = ['list()', '.tolist()']
n_range = [2**k for k in range(4, 20)]
xlabel = 'Rows in DataFrame'
eq_chk = lambda x,y: all([x,y])
numeric = lambda n: pd.Series(range(5)).repeat(n)
string = lambda n: pd.Series(['some word', 'another word', 'a word']).repeat(n)
datetime = lambda n: pd.to_datetime(pd.Series(['2012-05-14', '2046-12-31'])).repeat(n)
timedelta = lambda n: pd.to_timedelta(pd.Series([1,2]), unit='D').repeat(n)
categorical = lambda n: pd.Series(pd.Categorical([1, 2, 3, 1, 2, 3])).repeat(n)
for n, f in [('Numeric', numeric), ('Object dtype', string),
('Datetime', datetime), ('Timedelta', timedelta),
('Categorical', categorical)]:
plot(setup=f, kernels=kernels, labels=labels, n_range=n_range,
xlabel=xlabel, title=f'{n} column', equality_check=eq_chk);
解决方案 6:
由于这个问题引起了很多关注,并且有几种方法可以完成您的任务,因此让我提出几种选择。
顺便说一下,这些都是单行的;)
从以下开始:
df
cluster load_date budget actual fixed_price
0 A 1/1/2014 1000 4000 Y
1 A 2/1/2014 12000 10000 Y
2 A 3/1/2014 36000 2000 Y
3 B 4/1/2014 15000 10000 N
4 B 4/1/2014 12000 11500 N
5 B 4/1/2014 90000 11000 N
6 C 7/1/2014 22000 18000 N
7 C 8/1/2014 30000 28960 N
8 C 9/1/2014 53000 51200 N
潜在操作概述:
ser_aggCol (collapse each column to a list)
cluster [A, A, A, B, B, B, C, C, C]
load_date [1/1/2014, 2/1/2014, 3/1/2...
budget [1000, 12000, 36000, 15000...
actual [4000, 10000, 2000, 10000,...
fixed_price [Y, Y, Y, N, N, N, N, N, N]
dtype: object
ser_aggRows (collapse each row to a list)
0 [A, 1/1/2014, 1000, 4000, Y]
1 [A, 2/1/2014, 12000, 10000...
2 [A, 3/1/2014, 36000, 2000, Y]
3 [B, 4/1/2014, 15000, 10000...
4 [B, 4/1/2014, 12000, 11500...
5 [B, 4/1/2014, 90000, 11000...
6 [C, 7/1/2014, 22000, 18000...
7 [C, 8/1/2014, 30000, 28960...
8 [C, 9/1/2014, 53000, 51200...
dtype: object
df_gr (here you get lists for each cluster)
load_date budget actual fixed_price
cluster
A [1/1/2014, 2/1/2014, 3/1/2... [1000, 12000, 36000] [4000, 10000, 2000] [Y, Y, Y]
B [4/1/2014, 4/1/2014, 4/1/2... [15000, 12000, 90000] [10000, 11500, 11000] [N, N, N]
C [7/1/2014, 8/1/2014, 9/1/2... [22000, 30000, 53000] [18000, 28960, 51200] [N, N, N]
a list of separate dataframes for each cluster
df for cluster A
cluster load_date budget actual fixed_price
0 A 1/1/2014 1000 4000 Y
1 A 2/1/2014 12000 10000 Y
2 A 3/1/2014 36000 2000 Y
df for cluster B
cluster load_date budget actual fixed_price
3 B 4/1/2014 15000 10000 N
4 B 4/1/2014 12000 11500 N
5 B 4/1/2014 90000 11000 N
df for cluster C
cluster load_date budget actual fixed_price
6 C 7/1/2014 22000 18000 N
7 C 8/1/2014 30000 28960 N
8 C 9/1/2014 53000 51200 N
just the values of column load_date
0 1/1/2014
1 2/1/2014
2 3/1/2014
3 4/1/2014
4 4/1/2014
5 4/1/2014
6 7/1/2014
7 8/1/2014
8 9/1/2014
Name: load_date, dtype: object
just the values of column number 2
0 1000
1 12000
2 36000
3 15000
4 12000
5 90000
6 22000
7 30000
8 53000
Name: budget, dtype: object
just the values of row number 7
cluster C
load_date 8/1/2014
budget 30000
actual 28960
fixed_price N
Name: 7, dtype: object
============================== JUST FOR COMPLETENESS ==============================
you can convert a series to a list
['C', '8/1/2014', '30000', '28960', 'N']
<class 'list'>
you can convert a dataframe to a nested list
[['A', '1/1/2014', '1000', '4000', 'Y'], ['A', '2/1/2014', '12000', '10000', 'Y'], ['A', '3/1/2014', '36000', '2000', 'Y'], ['B', '4/1/2014', '15000', '10000', 'N'], ['B', '4/1/2014', '12000', '11500', 'N'], ['B', '4/1/2014', '90000', '11000', 'N'], ['C', '7/1/2014', '22000', '18000', 'N'], ['C', '8/1/2014', '30000', '28960', 'N'], ['C', '9/1/2014', '53000', '51200', 'N']]
<class 'list'>
the content of a dataframe can be accessed as a numpy.ndarray
[['A' '1/1/2014' '1000' '4000' 'Y']
['A' '2/1/2014' '12000' '10000' 'Y']
['A' '3/1/2014' '36000' '2000' 'Y']
['B' '4/1/2014' '15000' '10000' 'N']
['B' '4/1/2014' '12000' '11500' 'N']
['B' '4/1/2014' '90000' '11000' 'N']
['C' '7/1/2014' '22000' '18000' 'N']
['C' '8/1/2014' '30000' '28960' 'N']
['C' '9/1/2014' '53000' '51200' 'N']]
<class 'numpy.ndarray'>
代码:
# prefix ser refers to pd.Series object
# prefix df refers to pd.DataFrame object
# prefix lst refers to list object
import pandas as pd
import numpy as np
df=pd.DataFrame([
['A', '1/1/2014', '1000', '4000', 'Y'],
['A', '2/1/2014', '12000', '10000', 'Y'],
['A', '3/1/2014', '36000', '2000', 'Y'],
['B', '4/1/2014', '15000', '10000', 'N'],
['B', '4/1/2014', '12000', '11500', 'N'],
['B', '4/1/2014', '90000', '11000', 'N'],
['C', '7/1/2014', '22000', '18000', 'N'],
['C', '8/1/2014', '30000', '28960', 'N'],
['C', '9/1/2014', '53000', '51200', 'N']
], columns=['cluster', 'load_date', 'budget', 'actual', 'fixed_price'])
print('df',df, sep='
', end='
')
ser_aggCol=df.aggregate(lambda x: [x.tolist()], axis=0).map(lambda x:x[0])
print('ser_aggCol (collapse each column to a list)',ser_aggCol, sep='
', end='
')
ser_aggRows=pd.Series(df.values.tolist())
print('ser_aggRows (collapse each row to a list)',ser_aggRows, sep='
', end='
')
df_gr=df.groupby('cluster').agg(lambda x: list(x))
print('df_gr (here you get lists for each cluster)',df_gr, sep='
', end='
')
lst_dfFiltGr=[ df.loc[df['cluster']==val,:] for val in df['cluster'].unique() ]
print('a list of separate dataframes for each cluster', sep='
', end='
')
for dfTmp in lst_dfFiltGr:
print('df for cluster '+str(dfTmp.loc[dfTmp.index[0],'cluster']),dfTmp, sep='
', end='
')
ser_singleColLD=df.loc[:,'load_date']
print('just the values of column load_date',ser_singleColLD, sep='
', end='
')
ser_singleCol2=df.iloc[:,2]
print('just the values of column number 2',ser_singleCol2, sep='
', end='
')
ser_singleRow7=df.iloc[7,:]
print('just the values of row number 7',ser_singleRow7, sep='
', end='
')
print('='*30+' JUST FOR COMPLETENESS '+'='*30, end='
')
lst_fromSer=ser_singleRow7.tolist()
print('you can convert a series to a list',lst_fromSer, type(lst_fromSer), sep='
', end='
')
lst_fromDf=df.values.tolist()
print('you can convert a dataframe to a nested list',lst_fromDf, type(lst_fromDf), sep='
', end='
')
arr_fromDf=df.values
print('the content of a dataframe can be accessed as a numpy.ndarray',arr_fromDf, type(arr_fromDf), sep='
', end='
')
正如cs95所指出的,.values
从 pandas 版本 0.24开始,应该优先使用其他方法而不是 pandas属性,请参见此处。我在这里使用它,因为大多数人(到 2019 年)仍将使用不支持新建议的旧版本。您可以使用以下方法检查您的版本print(pd.__version__)
解决方案 7:
如果您的列只有一个值,pd.series.tolist()
则会产生错误。为了保证它适用于所有情况,请使用以下代码:
(
df
.filter(['column_name'])
.values
.reshape(1, -1)
.ravel()
.tolist()
)
解决方案 8:
如果您这样做df.T.values.tolist()
,它会生成列值列表的列表。
解决方案 9:
假设读取 excel 表后数据框的名称为df
,则取一个空列表(例如dataList
),逐行遍历数据框并附加到空列表中,例如-
dataList = [] #empty list
for index, row in df.iterrows():
mylist = [row.cluster, row.load_date, row.budget, row.actual, row.fixed_price]
dataList.append(mylist)
或者,
dataList = [] #empty list
for row in df.itertuples():
mylist = [row.cluster, row.load_date, row.budget, row.actual, row.fixed_price]
dataList.append(mylist)
不,如果您打印dataList
,您将获得其中的每一行作为列表dataList
。
解决方案 10:
如果要使用索引而不是列名(例如在循环中),则可以使用
for i in range(len(df.columns)):
print(df[df.columns[i]].to_list())
解决方案 11:
amount = list()
for col in df.columns:
val = list(df[col])
for v in val:
amount.append(v)